home *** CD-ROM | disk | FTP | other *** search
/ Aminet 35 / Aminet 35 (2000)(Schatztruhe)[!][Feb 2000].iso / Aminet / comm / tcp / samba_2.0.6.lha / source / amiga_rcs / amiga.c < prev    next >
Encoding:
C/C++ Source or Header  |  1999-12-25  |  179.4 KB  |  9,442 lines

  1. head    1.13;
  2. access;
  3. symbols
  4.     V1_12:1.13
  5.     V1_11:1.12
  6.     V1_10:1.11
  7.     V1_9:1.10
  8.     V1_8:1.9
  9.     V1_7:1.8
  10.     V1_6:1.7
  11.     V1_5:1.6
  12.     V1_4:1.4
  13.     V1_3:1.3
  14.     V1_2:1.2
  15.     V1_1:1.1;
  16. locks
  17.     olsen:1.13; strict;
  18. comment    @ * @;
  19.  
  20.  
  21. 1.13
  22. date    99.12.25.11.31.10;    author olsen;    state Exp;
  23. branches;
  24. next    1.12;
  25.  
  26. 1.12
  27. date    99.12.01.09.47.07;    author olsen;    state Exp;
  28. branches;
  29. next    1.11;
  30.  
  31. 1.11
  32. date    99.11.06.16.03.15;    author olsen;    state Exp;
  33. branches;
  34. next    1.10;
  35.  
  36. 1.10
  37. date    99.10.16.09.15.58;    author olsen;    state Exp;
  38. branches;
  39. next    1.9;
  40.  
  41. 1.9
  42. date    99.08.09.15.28.43;    author olsen;    state Exp;
  43. branches;
  44. next    1.8;
  45.  
  46. 1.8
  47. date    99.05.21.09.38.15;    author olsen;    state Exp;
  48. branches;
  49. next    1.7;
  50.  
  51. 1.7
  52. date    99.05.02.10.45.08;    author olsen;    state Exp;
  53. branches;
  54. next    1.6;
  55.  
  56. 1.6
  57. date    99.02.28.09.16.53;    author olsen;    state Exp;
  58. branches;
  59. next    1.5;
  60.  
  61. 1.5
  62. date    99.02.22.15.31.18;    author olsen;    state Exp;
  63. branches;
  64. next    1.4;
  65.  
  66. 1.4
  67. date    99.02.21.10.58.42;    author olsen;    state Exp;
  68. branches;
  69. next    1.3;
  70.  
  71. 1.3
  72. date    99.02.20.17.52.48;    author olsen;    state Exp;
  73. branches;
  74. next    1.2;
  75.  
  76. 1.2
  77. date    99.02.20.16.52.05;    author olsen;    state Exp;
  78. branches;
  79. next    1.1;
  80.  
  81. 1.1
  82. date    99.02.13.15.32.16;    author olsen;    state Exp;
  83. branches;
  84. next    ;
  85.  
  86.  
  87. desc
  88. @.
  89. @
  90.  
  91.  
  92. 1.13
  93. log
  94. @.
  95. @
  96. text
  97. @/*
  98.  * $Id: amiga.c 1.12 1999/12/01 09:47:07 olsen Exp olsen $
  99.  *
  100.  * :ts=4
  101.  *
  102.  * AmigaOS wrapper routines for Samba 2.0.0, using the AmiTCP V4 API
  103.  * and the SAS/C V6.58 compiler.
  104.  *
  105.  * Copyright (C) 1999 by Olaf `Olsen' Barthel <olsen@@sourcery.han.de>
  106.  *
  107.  * This program is free software; you can redistribute it and/or modify
  108.  * it under the terms of the GNU General Public License as published by
  109.  * the Free Software Foundation; either version 2 of the License, or
  110.  * (at your option) any later version.
  111.  *
  112.  * This program is distributed in the hope that it will be useful,
  113.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  114.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  115.  * GNU General Public License for more details.
  116.  *
  117.  * You should have received a copy of the GNU General Public License
  118.  * along with this program; if not, write to the Free Software
  119.  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  120.  */
  121.  
  122. /******************************************************************************/
  123.  
  124. #include <bsdsocket/socketbasetags.h>
  125. #include <libraries/usergroup.h>
  126.  
  127. #include <intuition/intuition.h>
  128. #include <libraries/locale.h>
  129. #include <exec/execbase.h>
  130. #include <exec/memory.h>
  131. #include <dos/dosextens.h>
  132. #include <dos/dostags.h>
  133. #include <devices/timer.h>
  134. #include <utility/date.h>
  135.  
  136. #include <clib/usergroup_protos.h>
  137. #include <clib/socket_protos.h>
  138.  
  139. #include <clib/intuition_protos.h>
  140. #include <clib/utility_protos.h>
  141. #include <clib/locale_protos.h>
  142. #include <clib/timer_protos.h>
  143. #include <clib/alib_protos.h>
  144. #include <clib/exec_protos.h>
  145. #include <clib/dos_protos.h>
  146.  
  147. #include <sys/socket.h>
  148. #include <sys/ioctl.h>
  149. #include <sys/time.h>
  150. #include <sys/dir.h>
  151.  
  152. #include <net/if.h>
  153.  
  154. #include <constructor.h>
  155. #include <stdarg.h>
  156. #include <stdlib.h>
  157. #include <string.h>
  158. #include <unistd.h>
  159. #include <signal.h>
  160. #include <utime.h>
  161. #include <errno.h>
  162. #include <stdio.h>
  163. #include <fcntl.h>
  164. #include <inetd.h>
  165. #include <stat.h>
  166. #include <ios1.h>
  167. #include <dos.h>
  168.  
  169. #include <pragmas/usergroup_pragmas.h>
  170. #include <pragmas/socket_pragmas.h>
  171.  
  172. #include <pragmas/exec_sysbase_pragmas.h>
  173. #include <pragmas/intuition_pragmas.h>
  174. #include <pragmas/utility_pragmas.h>
  175. #include <pragmas/locale_pragmas.h>
  176. #include <pragmas/timer_pragmas.h>
  177. #include <pragmas/dos_pragmas.h>
  178.  
  179. /******************************************************************************/
  180.  
  181. /* This is for the "iface_struct" definition. */
  182. #include "interfaces.h"
  183.  
  184. /******************************************************************************/
  185.  
  186. /*#define DEBUG*/
  187. #include "Assert.h"
  188.  
  189. /******************************************************************************/
  190.  
  191. STATIC VOID ReportProblem(const char *fmt, ...);
  192. STATIC VOID ForbidDOSCleanup(VOID);
  193. STATIC VOID PermitDOS(VOID);
  194. STATIC VOID ForbidDOS(VOID);
  195. STATIC VOID UnblockDescriptorCleanup(VOID);
  196. STATIC BOOL IsDescriptorNonblocking(int fd);
  197. STATIC VOID BlockDescriptor(int fd);
  198. STATIC VOID UnblockDescriptor(int fd);
  199. STATIC VOID SaveDescriptorCleanup(VOID);
  200. STATIC VOID RestoreDescriptor(struct UFB *ufb);
  201. STATIC BOOL SaveDescriptor(struct UFB *ufb);
  202. STATIC VOID UnmangleName(char **namePtr, struct MangleInfo *mi);
  203. STATIC int MangleName(char ** namePtr,struct MangleInfo * mi);
  204. STATIC VOID CloseUnlinkUnlockCleanup(VOID);
  205. STATIC VOID OpenDirCleanup(VOID);
  206. STATIC int TranslateRelativePath(char **namePtr, char *replace, int maxReplaceLen);
  207. STATIC VOID MapDescriptorSets(const fd_set *input_fds, int num_input_fds, fd_set *socket_fds, int *max_socket_fd_ptr, fd_set *file_fds, int *max_file_fd_ptr);
  208. STATIC VOID RemapDescriptorSets(const fd_set *socket_fds, int max_socket_fd, const fd_set *file_fds, int max_file_fd, fd_set *output_fds, int num_output_fds);
  209. STATIC VOID ConvertFileInfoToStat(struct MsgPort *port, struct FileInfoBlock *fib, struct stat *st);
  210. STATIC BOOL do_match(STRPTR str, STRPTR regexp);
  211. STATIC VOID nstrcpy_blank(const size_t maxSize, char *to, const char *from);
  212. STATIC BOOL SetFileSocket(FILE *stream, int sockfd);
  213. STATIC VOID DaemonInit(VOID);
  214. STATIC struct tm *ConvertTime(ULONG seconds);
  215. STATIC VOID MapIoErrToErrno(VOID);
  216. STATIC int MapFileNameAmigaToUnix(const char *amiga, char *unix, int maxUnixLen);
  217. STATIC VOID FlushSTDOUT(VOID);
  218. STATIC VOID CleanupSambaSemaphore(VOID);
  219. STATIC BOOL SetupSambaSemaphore(VOID);
  220. STATIC VOID RemoveLockedRegionNode(struct UFB *ufb, LONG start, LONG stop);
  221. STATIC VOID DeleteLockedRegionNode(struct LockedRegionNode *lrn);
  222. STATIC LONG CreateLockedRegionNode(struct LockedRegionNode **resultPtr);
  223. STATIC VOID DeleteFileLockNode(struct FileLockNode *fln);
  224. STATIC LONG CreateFileLockNode(struct UFB *ufb, struct FileLockNode **resultPtr);
  225. STATIC LONG FindFileLockNodeByFileHandle(BPTR fileHandle, struct FileLockNode **resultPtr);
  226. STATIC VOID FindFileLockNodeByDrawerAndName(BPTR parentDir, STRPTR fileName, struct FileLockNode **resultPtr);
  227. STATIC VOID CleanupFileLocks(int fd);
  228. STATIC int HandleFileLocking(int cmd, struct flock *l, struct UFB *ufb);
  229. STATIC struct LockedRegionNode *FindCollidingRegion(struct FileLockNode *fln, LONG start, LONG stop, BOOL shared);
  230.  
  231. /******************************************************************************/
  232.  
  233. int amiga_sigmask(int signum);
  234. int amiga_sigblock(int sigmask);
  235. int amiga_sigsetmask(int sigmask);
  236. int amiga_unlink(char *name);
  237. int amiga_open(char *name, int mode, int prot);
  238. int amiga_chdir(char *path);
  239. DIR *amiga_opendir(char *dirName);
  240. VOID amiga_closedir(DIR *dir);
  241. struct dirent *amiga_readdir(DIR *dir);
  242. int amiga_mkdir(char *name, int mode);
  243. int amiga_rmdir(char *name);
  244. int amiga_creat(char *name, int prot);
  245. FILE *amiga_fopen(char *name, char *mode);
  246. int amiga_rename(char *old, char *new);
  247. char *amiga_getcwd(char *buf, size_t size);
  248. int amiga_ftruncate(int fd, off_t size);
  249. int amiga_accept(int sockfd, struct sockaddr *cliaddr, int *addrlen);
  250. int amiga_bind(int sockfd, struct sockaddr *name, int namelen);
  251. int amiga_close(int fd);
  252. int amiga_connect(int sockfd, struct sockaddr *name, int namelen);
  253. int amiga_getpeername(int sockfd, struct sockaddr *name, int *namelen);
  254. int amiga_getsockopt(int sockfd, int level, int optname, VOID *optval, int *optlen);
  255. int amiga_ioctl(int fd, unsigned long request, char *arg);
  256. int amiga_listen(int sockfd, int backlog);
  257. int amiga_read(int fd, VOID *data, unsigned int size);
  258. int amiga_recvfrom(int sockfd, VOID *buff, int len, int flags, struct sockaddr *from, int *fromlen);
  259. int amiga_select(int num_fds, fd_set *read_fds, fd_set *write_fds, fd_set *except_fds, struct timeval *timeout);
  260. int amiga_sendto(int sockfd, VOID *buff, int len, int flags, struct sockaddr *to, int tolen);
  261. int amiga_setsockopt(int sockfd, int level, int optname, VOID *optval, int optlen);
  262. int amiga_socket(int domain, int type, int protocol);
  263. int amiga_write(int fd, VOID *data, unsigned int size);
  264. int amiga_stat(char *name, struct stat *st);
  265. int amiga_lstat(char *name, struct stat *statstruct);
  266. int amiga_fstat(int fd, struct stat *st);
  267. int amiga_chmod(char *name, int mode);
  268. int amiga_dup(int fd);
  269. int amiga_dup2(int old_fd, int new_fd);
  270. int amiga_chown(char *name, uid_t uid, gid_t gid);
  271. int amiga_setegid(gid_t g);
  272. int amiga_seteuid(uid_t u);
  273. int amiga_gettimeofday(struct timeval *tv);
  274. int amiga_utime(char *name, struct utimbuf *time);
  275. VOID amiga_sleep(unsigned int seconds);
  276. char *amiga_crypt(char *key, char *salt);
  277. char *amiga_getpass(char *prompt);
  278. int amiga_setgid(gid_t id);
  279. int amiga_setgroups(int ngroups, gid_t *groups);
  280. gid_t amiga_getgid(VOID);
  281. struct group *amiga_getgrgid(gid_t gid);
  282. struct group *amiga_getgrnam(char *name);
  283. int amiga_getgroups(int ngroups, gid_t *groups);
  284. struct hostent *amiga_gethostbyaddr(char *addr, int len, int type);
  285. struct hostent *amiga_gethostbyname(char *name);
  286. struct netent *amiga_getnetbyname(char *name);
  287. int amiga_gethostname(char *hostname, int size);
  288. struct passwd *amiga_getpwnam(char *name);
  289. struct passwd *amiga_getpwuid(uid_t uid);
  290. uid_t amiga_getuid(VOID);
  291. gid_t amiga_getegid(VOID);
  292. uid_t amiga_geteuid(VOID);
  293. int amiga_initgroups(char *name, gid_t basegroup);
  294. int amiga_setuid(uid_t id);
  295. int amiga_umask(int mask);
  296. unsigned long amiga_inet_addr(char *addr);
  297. char *amiga_inet_ntoa(struct in_addr in);
  298. int amiga_getopt(int argc, char *argv[], char *opts);
  299. int amiga_system(char *cmd);
  300. int amiga_fork(VOID);
  301. VOID __tzset(VOID);
  302. time_t time(time_t *timeptr);
  303. struct tm *gmtime(const time_t *t);
  304. struct tm *localtime(const time_t *t);
  305. int amiga_strcasecmp(char *a, char *b);
  306. int amiga_strncasecmp(char *a, char *b, int len);
  307. VOID (*amiga_signal(int which,VOID (* action)(int)))(int);
  308. VOID amiga_alarm(int seconds);
  309. int amiga_waitpid(pid_t pid, int *status, int options);
  310. long amiga_setsid(VOID);
  311. int amiga_setreuid(uid_t real, uid_t eff);
  312. int amiga_setregid(gid_t real, gid_t eff);
  313. int amiga_fcntl(int fd, int cmd, unsigned long arg);
  314. int amiga_getsockname(int sockfd, struct sockaddr *name, int *namelen);
  315. int amiga_statfs(char *name, struct statfs *f);
  316. int amiga_execl(char *path, char *arg, ...);
  317. char *amiga_strerror(int error);
  318. int amiga_access(char *name, int modes);
  319. off_t amiga_lseek(int fd, off_t offset, int mode);
  320. int amiga_chroot(char *name);
  321. int amiga_kill(pid_t pid, int sig);
  322. pid_t amiga_getpid(VOID);
  323. int amiga_fgetc(FILE *in);
  324. char *amiga_fgets(char *str, int n, FILE *in);
  325. int amiga_fputs(const char *str, FILE *out);
  326. int amiga_puts(const char *str);
  327. int amiga_vfprintf(FILE *out, const char *fmt, va_list args);
  328. int amiga_fprintf(FILE *out, const char *fmt, ...);
  329. int amiga_printf(const char *fmt, ...);
  330. size_t amiga_fwrite(const void *data, size_t blockSize, size_t numBlocks, FILE *out);
  331. size_t amiga_fread(void *data, size_t blockSize, size_t numBlocks, FILE *in);
  332. int amiga_fclose(FILE *stream);
  333. int amiga_fflush(FILE *stream);
  334. int amiga_fseek(FILE *stream, long int offset, int mode);
  335. long int amiga_ftell(FILE *stream);
  336. int amiga_setvbuf(FILE *fp, char *buff, int type, size_t size);
  337. int amiga_fputc(int c,FILE *stream);
  338. VOID amiga_setbuf(FILE *stream,char *buffer);
  339.  
  340. /******************************************************************************/
  341.  
  342. VOID __regargs __chkabort(VOID);
  343. VOID _CXOVF(VOID);
  344. VOID __regargs _CXBRK(VOID);
  345.  
  346. /******************************************************************************/
  347.  
  348. /* These are in the Samba runtime library. */
  349. extern int vsnprintf (char *str, size_t count, const char *fmt, va_list arg);
  350. extern int snprintf (char *str, size_t count, const char *fmt, ...);
  351.  
  352. /******************************************************************************/
  353.  
  354. #define ZERO    ((BPTR)0L)
  355. #define ERROR    (-1)
  356. #define OK        (0)
  357. #define SAME    (0)
  358. #define NO        !
  359. #define NOT        !
  360. #define DONT    !
  361. #define CANNOT    !
  362. #define BUSY    (NULL)
  363. #define NO_FLAG    (0)
  364.  
  365. /******************************************************************************/
  366.  
  367. #define FLAG_IS_SET(v,f)    (((v) & (f)) == (f))
  368. #define FLAG_IS_CLEAR(v,f)    (((v) & (f)) == 0)
  369.  
  370. #define SET_FLAG(v,f)        (v |=  (f))
  371. #define CLEAR_FLAG(v,f)        (v &= ~(f))
  372.  
  373. /******************************************************************************/
  374.  
  375. #define STRING_IS_EMPTY(s)    (s[0] == '\0')
  376. #define NUM_ENTRIES(t)        (sizeof(t) / sizeof(t[0]))
  377.  
  378. /******************************************************************************/
  379.  
  380. #define FIB_IS_FILE(fib)    ((fib)->fib_DirEntryType < 0)
  381. #define FIB_IS_DRAWER(fib)    ((fib)->fib_DirEntryType >= 0 && (fib)->fib_DirEntryType != ST_SOFTLINK)
  382.  
  383. /******************************************************************************/
  384.  
  385. #define UFB_IS_SOCKET        0x0800
  386. #define UFB_IS_NON_BLOCKING    0x1000
  387. #define UFB_UNLINK            0x2000
  388. #define UFB_LOCKED            0x4000
  389.  
  390. #define UNIX_TIME_OFFSET    252482400
  391.  
  392. #define MAX_BSTR_LEN        256
  393. #define MAX_FILENAME_LEN    512
  394. #define MAX_FFS_NAME_LEN    30
  395.  
  396. /******************************************************************************/
  397.  
  398. long __oslibversion = 37;
  399.  
  400. /******************************************************************************/
  401.  
  402. extern struct Library * SysBase;
  403. extern struct Library * DOSBase;
  404. extern struct Library * UtilityBase;
  405.  
  406. /******************************************************************************/
  407.  
  408. STATIC struct Device * TimerBase;
  409. STATIC struct MsgPort * TimerPort;
  410. STATIC struct timerequest * TimerRequest;
  411. STATIC LONG MinutesWest;
  412.  
  413. /******************************************************************************/
  414.  
  415. STATIC struct Library * SocketBase;
  416. STATIC struct Library * UserGroupBase;
  417.  
  418. /******************************************************************************/
  419.  
  420. #if defined(_M68020) && defined(_M68881)
  421. #define MACHINE_TYPE "['020+FPU]"
  422. #elif defined(_M68020)
  423. #define MACHINE_TYPE "['020]"
  424. #else
  425. #define MACHINE_TYPE "[68k]"
  426. #endif
  427.  
  428. /******************************************************************************/
  429.  
  430. #include "Amiga_Samba_rev.h"
  431. char * VersionTag = VERSTAG " " MACHINE_TYPE " Samba version 2.0.0 ported by Olaf `Olsen' Barthel <olsen@@sourcery.han.de>";
  432.  
  433. /******************************************************************************/
  434.  
  435. /* This is for backwards compatibility with Kickstart 2.04 and
  436.  * avoids a deadlock when trying to get a shared lock on
  437.  * a semaphore already held in exclusive mode by the same Task.
  438.  */
  439. STATIC VOID
  440. SafeObtainSemaphoreShared(struct SignalSemaphore * semaphore)
  441. {
  442.     /* Do it right with Kickstart 3.x. */
  443.     if(SysBase->lib_Version >= 39)
  444.     {
  445.         ObtainSemaphoreShared(semaphore);
  446.     }
  447.     else
  448.     {
  449.         /* Try to get the shared semaphore */
  450.         if(CANNOT AttemptSemaphoreShared(semaphore))
  451.         {
  452.             /* Check if we can get the exclusive version */
  453.             if(CANNOT AttemptSemaphore(semaphore))
  454.             {
  455.                 /* Oh well, wait for the shared lock */
  456.                 ObtainSemaphoreShared(semaphore);
  457.             }
  458.         }
  459.     }
  460. }
  461.  
  462. /******************************************************************************/
  463.  
  464. STATIC BOOL AllowBreak = TRUE;
  465.  
  466. STATIC BOOL
  467. CheckAbort(VOID)
  468. {
  469.     BOOL result;
  470.  
  471.     result = (BOOL)(AllowBreak && FLAG_IS_SET(SetSignal(0,SIGBREAKF_CTRL_C),SIGBREAKF_CTRL_C));
  472.  
  473.     return(result);
  474. }
  475.  
  476. VOID __regargs
  477. __chkabort(VOID)
  478. {
  479.     if(CheckAbort())
  480.         raise(SIGINT);
  481. }
  482.  
  483. int
  484. amiga_sigmask(int signum)
  485. {
  486.     int result = 0;
  487.  
  488.     ENTER();
  489.  
  490.     SHOWVALUE(signum);
  491.  
  492.     if(signum == SIGTERM || signum == SIGINT)
  493.         result = (1<<SIGINT);
  494.  
  495.     RETURN(result);
  496.     return(result);
  497. }
  498.  
  499. int
  500. amiga_sigblock(int sigmask)
  501. {
  502.     BOOL oldAllowBreak = AllowBreak;
  503.     int result = 0;
  504.  
  505.     ENTER();
  506.  
  507.     SHOWVALUE(sigmask);
  508.  
  509.     if(DONT AllowBreak)
  510.         result = (1<<SIGINT);
  511.  
  512.     if(FLAG_IS_SET(sigmask,(1<<SIGINT)))
  513.     {
  514.         AllowBreak = FALSE;
  515.  
  516.         if(oldAllowBreak != AllowBreak)
  517.         {
  518.             SocketBaseTags(
  519.                 SBTM_SETVAL(SBTC_BREAKMASK),NO_FLAG,
  520.             TAG_END);
  521.         }
  522.     }
  523.  
  524.     RETURN(result);
  525.     return(result);
  526. }
  527.  
  528. int
  529. amiga_sigsetmask(int sigmask)
  530. {
  531.     BOOL oldAllowBreak = AllowBreak;
  532.     int result = 0;
  533.  
  534.     ENTER();
  535.  
  536.     SHOWVALUE(sigmask);
  537.  
  538.     AllowBreak = FLAG_IS_CLEAR(sigmask,(1<<SIGINT));
  539.     if(oldAllowBreak != AllowBreak)
  540.     {
  541.         ULONG mask;
  542.  
  543.         if(AllowBreak)
  544.             mask = SIGBREAKF_CTRL_C;
  545.         else
  546.             mask = NO_FLAG;
  547.  
  548.         SocketBaseTags(
  549.             SBTM_SETVAL(SBTC_BREAKMASK),mask,
  550.         TAG_END);
  551.     }
  552.  
  553.     RETURN(result);
  554.     return(result);
  555. }
  556.  
  557. /******************************************************************************/
  558.  
  559. STATIC VOID
  560. ReportProblem(const char *fmt,...)
  561. {
  562.     extern const STRPTR _ProgramName;
  563.     BOOL useRequester = TRUE;
  564.     va_list varArgs;
  565.  
  566.     ASSERT(fmt != NULL);
  567.  
  568.     va_start(varArgs,fmt);
  569.  
  570.     /* Launched from Workbench? */
  571.     if(WBenchMsg == NULL)
  572.     {
  573.         if(DOSBase->lib_Version >= 37)
  574.         {
  575.             BPTR stream;
  576.  
  577.             /* Make a copy of the current terminal
  578.              * output stream. This avoids sending
  579.              * an error message through a redirected
  580.              * standard output stream, the output
  581.              * will go straight to the terminal.
  582.              */
  583.             stream = Open("CONSOLE:",MODE_NEWFILE);
  584.             if(stream != ZERO)
  585.             {
  586.                 struct FileHandle * fh = BADDR(stream);
  587.  
  588.                 /* Check if the output was redirected
  589.                  * to "NIL:"; if not, print the error
  590.                  * error message.
  591.                  */
  592.                 if(fh->fh_Type != NULL)
  593.                 {
  594.                     FPrintf(stream,"%s: ",_ProgramName);
  595.                     VFPrintf(stream,(STRPTR)fmt,(APTR)varArgs);
  596.                     FPrintf(stream,"\a\n");
  597.  
  598.                     useRequester = FALSE;
  599.                 }
  600.  
  601.                 Close(stream);
  602.             }
  603.         }
  604.     }
  605.  
  606.     /* Oh well, don't use the Shell for output. Put up a
  607.      * requester.
  608.      */
  609.     if(useRequester)
  610.     {
  611.         struct Library * IntuitionBase;
  612.  
  613.         IntuitionBase = OpenLibrary("intuition.library",37);
  614.         if(IntuitionBase != NULL)
  615.         {
  616.             struct Window * reqWindow;
  617.             struct EasyStruct es;
  618.             char title[100];
  619.  
  620.             snprintf(title,sizeof(title)-1,"Amiga Samba Error (%s)",FilePart(_ProgramName));
  621.             title[sizeof(title)-1] = '\0';
  622.  
  623.             memset(&es,0,sizeof(es));
  624.  
  625.             es.es_StructSize    = sizeof(es);
  626.             es.es_Title            = (STRPTR)title;
  627.             es.es_TextFormat    = (STRPTR)fmt;
  628.             es.es_GadgetFormat    = "Ok";
  629.  
  630.             reqWindow = BuildEasyRequestArgs(NULL,&es,0,(APTR)varArgs);
  631.             if(reqWindow != NULL)
  632.             {
  633.                 struct timerequest * timeRequest = NULL;
  634.                 struct MsgPort * timePort;
  635.                 BOOL timerOpen = FALSE;
  636.                 ULONG windowSignal;
  637.                 ULONG timerSignal;
  638.                 ULONG signals;
  639.                 BOOL done;
  640.  
  641.                 timePort = CreateMsgPort();
  642.                 if(timePort != NULL)
  643.                 {
  644.                     timeRequest = CreateIORequest(timePort,sizeof(*timeRequest));
  645.                     if(timeRequest != NULL)
  646.                     {
  647.                         if(OpenDevice(TIMERNAME,UNIT_VBLANK,(struct IORequest *)timeRequest,0) == OK)
  648.                             timerOpen = TRUE;
  649.                     }
  650.                 }
  651.  
  652.                 windowSignal = (1UL << reqWindow->UserPort->mp_SigBit);
  653.  
  654.                 if(timerOpen)
  655.                 {
  656.                     timerSignal = (1UL << timePort->mp_SigBit);
  657.  
  658.                     timeRequest->tr_node.io_Command    = TR_ADDREQUEST;
  659.                     timeRequest->tr_time.tv_secs    = 30;
  660.                     timeRequest->tr_time.tv_micro    = 0;
  661.  
  662.                     SendIO((struct IORequest *)timeRequest);
  663.                 }
  664.                 else
  665.                 {
  666.                     timerSignal = 0;
  667.                 }
  668.  
  669.                 DisplayBeep(reqWindow->WScreen);
  670.  
  671.                 done = FALSE;
  672.                 do
  673.                 {
  674.                     signals = Wait(windowSignal | timerSignal);
  675.  
  676.                     if(FLAG_IS_SET(signals,windowSignal))
  677.                     {
  678.                         if(SysReqHandler(reqWindow,NULL,FALSE) >= 0)
  679.                             done = TRUE;
  680.                     }
  681.  
  682.                     if(FLAG_IS_SET(signals,timerSignal))
  683.                     {
  684.                         done = TRUE;
  685.                     }
  686.                 }
  687.                 while(NOT done);
  688.  
  689.                 if(timerOpen)
  690.                 {
  691.                     if(CheckIO((struct IORequest *)timeRequest) == BUSY)
  692.                         AbortIO((struct IORequest *)timeRequest);
  693.  
  694.                     WaitIO((struct IORequest *)timeRequest);
  695.  
  696.                     CloseDevice((struct IORequest *)timeRequest);
  697.                 }
  698.  
  699.                 DeleteIORequest((struct IORequest *)timeRequest);
  700.                 DeleteMsgPort(timePort);
  701.  
  702.                 FreeSysRequest(reqWindow);
  703.             }
  704.  
  705.             CloseLibrary(IntuitionBase);
  706.         }
  707.     }
  708.  
  709.     va_end(varArgs);
  710. }
  711.  
  712. /******************************************************************************/
  713.  
  714. STATIC APTR OldWindowPtr;
  715. STATIC LONG ForbidCount;
  716.  
  717. STATIC VOID
  718. ForbidDOSCleanup(VOID)
  719. {
  720.     if(ForbidCount > 0)
  721.     {
  722.         struct Process * pr = (struct Process *)FindTask(NULL);
  723.  
  724.         pr->pr_WindowPtr = OldWindowPtr;
  725.  
  726.         ForbidCount = 0;
  727.     }
  728. }
  729.  
  730. STATIC VOID
  731. PermitDOS(VOID)
  732. {
  733.     ASSERT(ForbidCount > 0);
  734.  
  735.     if(--ForbidCount == 0)
  736.     {
  737.         struct Process * pr = (struct Process *)FindTask(NULL);
  738.  
  739.         pr->pr_WindowPtr = OldWindowPtr;
  740.     }
  741. }
  742.  
  743. STATIC VOID
  744. ForbidDOS(VOID)
  745. {
  746.     if(ForbidCount++ == 0)
  747.     {
  748.         struct Process * pr = (struct Process *)FindTask(NULL);
  749.  
  750.         OldWindowPtr = pr->pr_WindowPtr;
  751.         pr->pr_WindowPtr = (APTR)-1;
  752.     }
  753. }
  754.  
  755. /******************************************************************************/
  756.  
  757. #define SINGLE_CHARACTER_MODE    (1)
  758. #define BUFFERED_MODE            (0)
  759.  
  760. STATIC int MaxNonblockingDescriptor = -1;
  761.  
  762. STATIC VOID
  763. UnblockDescriptorCleanup(VOID)
  764. {
  765.     struct UFB * ufb;
  766.     int fd;
  767.  
  768.     /* We look for descriptors we switched into
  769.      * non-blocking mode and reset them back
  770.      * to blocking mode.
  771.      */
  772.     for(fd = 0 ; fd <= MaxNonblockingDescriptor ; fd++)
  773.     {
  774.         ufb = chkufb(fd);
  775.         if(ufb != NULL && FLAG_IS_SET(ufb->ufbflg,UFB_IS_NON_BLOCKING))
  776.         {
  777.             SetMode((BPTR)ufb->ufbfh,BUFFERED_MODE);
  778.  
  779.             CLEAR_FLAG(ufb->ufbflg,UFB_IS_NON_BLOCKING);
  780.         }
  781.     }
  782. }
  783.  
  784. STATIC BOOL
  785. IsDescriptorNonblocking(int fd)
  786. {
  787.     struct UFB * ufb;
  788.     BOOL result = FALSE;
  789.  
  790.     /* Verify if a descriptor was switched into non-blocking mode. */
  791.     ufb = chkufb(fd);
  792.     if(ufb != NULL)
  793.         result = FLAG_IS_SET(ufb->ufbflg,UFB_IS_NON_BLOCKING);
  794.  
  795.     return(result);
  796. }
  797.  
  798. STATIC VOID
  799. BlockDescriptor(int fd)
  800. {
  801.     struct UFB * ufb;
  802.  
  803.     /* This resets a file descriptor to blocking mode,
  804.      * once it has been set to blocking mode.
  805.      */
  806.     ufb = chkufb(fd);
  807.     if(ufb != NULL)
  808.     {
  809.         if(FLAG_IS_SET(ufb->ufbflg,UFB_IS_NON_BLOCKING))
  810.         {
  811.             SetMode((BPTR)ufb->ufbfh,BUFFERED_MODE);
  812.  
  813.             CLEAR_FLAG(ufb->ufbflg,UFB_IS_NON_BLOCKING);
  814.         }
  815.     }
  816. }
  817.  
  818. STATIC VOID
  819. UnblockDescriptor(int fd)
  820. {
  821.     struct UFB * ufb;
  822.  
  823.     ufb = chkufb(fd);
  824.     if(ufb != NULL)
  825.     {
  826.         /* Make sure we got a file and it's not already
  827.          * in non-blocking mode.
  828.          */
  829.         if(FLAG_IS_CLEAR(ufb->ufbflg,UFB_IS_SOCKET) && FLAG_IS_CLEAR(ufb->ufbflg,UFB_IS_NON_BLOCKING))
  830.         {
  831.             /* Try to flip it into single character mode,
  832.              * which we treat as "non-blocking" mode.
  833.              */
  834.             if(SetMode((BPTR)ufb->ufbfh,SINGLE_CHARACTER_MODE))
  835.             {
  836.                 SET_FLAG(ufb->ufbflg,UFB_IS_NON_BLOCKING);
  837.  
  838.                 /* Remember which one we switched. */
  839.                 if(MaxNonblockingDescriptor < fd)
  840.                     MaxNonblockingDescriptor = fd;
  841.             }
  842.         }
  843.     }
  844. }
  845.  
  846. /******************************************************************************/
  847.  
  848. struct SavedDescriptorNode
  849. {
  850.     struct MinNode    sdn_MinNode;
  851.     struct UFB *    sdn_UFB;
  852.     BPTR            sdn_FileHandle;
  853. };
  854.  
  855. STATIC BOOL DescriptorListInitialized = FALSE;
  856. STATIC struct List DescriptorList;
  857.  
  858. STATIC VOID
  859. SaveDescriptorCleanup(VOID)
  860. {
  861.     /* This routine restores all file descriptors
  862.      * we used to map to sockets to use proper file
  863.      * handles.
  864.      */
  865.     if(DescriptorListInitialized)
  866.     {
  867.         struct SavedDescriptorNode * sdn;
  868.  
  869.         for(sdn = (struct SavedDescriptorNode *)DescriptorList.lh_Head ;
  870.             sdn->sdn_MinNode.mln_Succ != NULL ;
  871.             sdn = (struct SavedDescriptorNode *)sdn->sdn_MinNode.mln_Succ)
  872.         {
  873.             /* Make sure that if this file is bound to
  874.              * a socket, the socket is closed.
  875.              */
  876.             if(FLAG_IS_SET(sdn->sdn_UFB->ufbflg,UFB_IS_SOCKET))
  877.             {
  878.                 CloseSocket(sdn->sdn_UFB->ufbfh);
  879.  
  880.                 CLEAR_FLAG(sdn->sdn_UFB->ufbflg,UFB_IS_SOCKET);
  881.             }
  882.  
  883.             sdn->sdn_UFB->ufbfh = sdn->sdn_FileHandle;
  884.         }
  885.     }
  886. }
  887.  
  888. STATIC VOID
  889. RestoreDescriptor(struct UFB * ufb)
  890. {
  891.     ASSERT(ufb != NULL);
  892.  
  893.     /* This routine restores one particular file descriptor
  894.      * which was used as a socket to refer to a proper
  895.      * file handle.
  896.      */
  897.     if(DescriptorListInitialized)
  898.     {
  899.         struct SavedDescriptorNode * sdn;
  900.  
  901.         for(sdn = (struct SavedDescriptorNode *)DescriptorList.lh_Head ;
  902.             sdn->sdn_MinNode.mln_Succ != NULL ;
  903.             sdn = (struct SavedDescriptorNode *)sdn->sdn_MinNode.mln_Succ)
  904.         {
  905.             if(sdn->sdn_UFB == ufb)
  906.             {
  907.                 sdn->sdn_UFB->ufbfh = sdn->sdn_FileHandle;
  908.  
  909.                 Remove((struct Node *)sdn);
  910.                 free(sdn);
  911.  
  912.                 break;
  913.             }
  914.         }
  915.     }
  916. }
  917.  
  918. STATIC BOOL
  919. SaveDescriptor(struct UFB * ufb)
  920. {
  921.     struct SavedDescriptorNode * sdn;
  922.     BOOL result = FALSE;
  923.  
  924.     ASSERT(ufb != NULL);
  925.  
  926.     /* Set up the descriptor list, unless it's already
  927.      * initialized.
  928.      */
  929.     if(NOT DescriptorListInitialized)
  930.     {
  931.         NewList(&DescriptorList);
  932.         DescriptorListInitialized = TRUE;
  933.     }
  934.  
  935.     sdn = malloc(sizeof(*sdn));
  936.     if(sdn != NULL)
  937.     {
  938.         memset(sdn,0,sizeof(*sdn));
  939.  
  940.         /* Remember the file buffer and the file
  941.          * handle attached to the descriptor.
  942.          */
  943.         sdn->sdn_UFB        = ufb;
  944.         sdn->sdn_FileHandle    = ufb->ufbfh;
  945.  
  946.         AddHead(&DescriptorList,(struct Node *)sdn);
  947.  
  948.         result = TRUE;
  949.     }
  950.  
  951.     return(result);
  952. }
  953.  
  954. /******************************************************************************/
  955.  
  956. STATIC BOOL InitialCurrentDirInitialized = FALSE;
  957. STATIC BPTR InitialCurrentDir;
  958. STATIC BPTR ChangedCurrentDir;
  959.  
  960. CBMLIB_DESTRUCTOR(CloseLibsAndDevs)
  961. {
  962.     ENTER();
  963.  
  964.     /* Return to the directory we were in
  965.      * when we started.
  966.      */
  967.     if(InitialCurrentDirInitialized)
  968.     {
  969.         CurrentDir(InitialCurrentDir);
  970.         InitialCurrentDirInitialized = FALSE;
  971.     }
  972.  
  973.     /* If the current directory was changed, unlock it. */
  974.     if(ChangedCurrentDir != ZERO)
  975.     {
  976.         UnLock(ChangedCurrentDir);
  977.         ChangedCurrentDir = ZERO;
  978.     }
  979.  
  980.     CleanupSambaSemaphore();
  981.  
  982.     if(TimerRequest != NULL)
  983.     {
  984.         if(TimerRequest->tr_node.io_Device != NULL)
  985.             CloseDevice((struct IORequest *)TimerRequest);
  986.  
  987.         DeleteIORequest((struct IORequest *)TimerRequest);
  988.         TimerRequest = NULL;
  989.     }
  990.  
  991.     if(TimerPort != NULL)
  992.     {
  993.         DeleteMsgPort(TimerPort);
  994.         TimerPort = NULL;
  995.     }
  996.  
  997.     TimerBase = NULL;
  998.  
  999.     if(SocketBase != NULL)
  1000.     {
  1001.         CloseLibrary(SocketBase);
  1002.         SocketBase = NULL;
  1003.     }
  1004.  
  1005.     if(UserGroupBase != NULL)
  1006.     {
  1007.         CloseLibrary(UserGroupBase);
  1008.         UserGroupBase = NULL;
  1009.     }
  1010.  
  1011.     LEAVE();
  1012. }
  1013.  
  1014. CBMLIB_CONSTRUCTOR(OpenLibsAndDevs)
  1015. {
  1016.     extern STRPTR _ProgramName;
  1017.     BOOL sambaSemaphoreCreated;
  1018.     struct LocaleBase * LocaleBase;
  1019.     char *timerError = "";
  1020.     BPTR sambaLock;
  1021.     int result = ERROR;
  1022.  
  1023.     SETPROGRAMNAME(_ProgramName);
  1024.     SETDEBUGLEVEL(0);
  1025.  
  1026.     ENTER();
  1027.  
  1028.     SocketBase = OpenLibrary("bsdsocket.library",4);
  1029.     UserGroupBase = OpenLibrary("usergroup.library",1);
  1030.  
  1031.     if(SysBase->lib_Version >= 37)
  1032.     {
  1033.         TimerPort = CreateMsgPort();
  1034.         if(TimerPort != NULL)
  1035.         {
  1036.             TimerRequest = (struct timerequest *)CreateIORequest(TimerPort,sizeof(*TimerRequest));
  1037.             if(TimerRequest != NULL)
  1038.             {
  1039.                 if(OpenDevice(TIMERNAME,UNIT_VBLANK,(struct IORequest *)TimerRequest,NULL) == OK)
  1040.                     TimerBase = TimerRequest->tr_node.io_Device;
  1041.                 else
  1042.                     timerError = "opening \"timer.device\"";
  1043.             }
  1044.             else
  1045.             {
  1046.                 timerError = "creating timer I/O request";
  1047.             }
  1048.         }
  1049.         else
  1050.         {
  1051.             timerError = "creating timer message port";
  1052.         }
  1053.     }
  1054.  
  1055.     /* Try to determine this machine's time zone. */
  1056.     LocaleBase = (struct LocaleBase *)OpenLibrary("locale.library",38);
  1057.     if(LocaleBase != NULL)
  1058.     {
  1059.         struct Locale * locale;
  1060.  
  1061.         locale = OpenLocale(NULL);
  1062.         MinutesWest = locale->loc_GMTOffset;
  1063.         CloseLocale(locale);
  1064.  
  1065.         CloseLibrary((struct Library *)LocaleBase);
  1066.     }
  1067.  
  1068.     ForbidDOS();
  1069.  
  1070.     /* Try to get a lock on the "Samba:" directory,
  1071.      * just to make sure the assignment is in place.
  1072.      */
  1073.     sambaLock = Lock("Samba:",SHARED_LOCK);
  1074.     if(sambaLock != ZERO)
  1075.         UnLock(sambaLock);
  1076.  
  1077.     PermitDOS();
  1078.  
  1079.     /* Initialize the global process ID database. */
  1080.     sambaSemaphoreCreated = SetupSambaSemaphore();
  1081.  
  1082.     if(SocketBase != NULL && UserGroupBase != NULL && TimerBase != NULL &&
  1083.        sambaLock != ZERO && sambaSemaphoreCreated)
  1084.     {
  1085.         STATIC long h_errno = 0;
  1086.         struct timeval now;
  1087.         int error;
  1088.  
  1089.         error = SocketBaseTags(
  1090.             SBTM_SETVAL(SBTC_ERRNOPTR(sizeof(errno))),    &errno,
  1091.             SBTM_SETVAL(SBTC_HERRNOLONGPTR),            &h_errno,
  1092.             SBTM_SETVAL(SBTC_LOGTAGPTR),                _ProgramName,
  1093.             SBTM_SETVAL(SBTC_BREAKMASK),                SIGBREAKF_CTRL_C,
  1094.         TAG_END);
  1095.         if(error != OK)
  1096.         {
  1097.             ReportProblem("Error initializing socket data (error=%ld).",error);
  1098.             goto out;
  1099.         }
  1100.  
  1101.         error = ug_SetupContextTags(_ProgramName,
  1102.             UGT_ERRNOPTR(sizeof(errno)),&errno,
  1103.         TAG_END);
  1104.         if(error != OK)
  1105.         {
  1106.             ReportProblem("Error initializing user group data (error=%ld).",error);
  1107.             goto out;
  1108.         }
  1109.  
  1110.         /* Use a new random number seed. */
  1111.         GetSysTime((APTR)&now);
  1112.         srand(now.tv_secs);
  1113.     }
  1114.     else
  1115.     {
  1116.         if(SocketBase == NULL)
  1117.             ReportProblem("Error opening \"bsdsocket.library\" V4.");
  1118.         else if (UserGroupBase == NULL)
  1119.             ReportProblem("Error opening \"usergroup.library\" V1.");
  1120.         else if (TimerBase == NULL)
  1121.             ReportProblem("Error %s.",timerError);
  1122.         else if (sambaLock == ZERO)
  1123.             ReportProblem("Error finding \"Samba:\" assignment.");
  1124.         else if (NOT sambaSemaphoreCreated)
  1125.             ReportProblem("Error creating Samba semaphore.");
  1126.  
  1127.         goto out;
  1128.     }
  1129.  
  1130.     /* Initialize the current time zone variable. */
  1131.     __tzset();
  1132.  
  1133.     result = OK;
  1134.  
  1135. out:
  1136.  
  1137.     RETURN(result);
  1138.     return(result);
  1139. }
  1140.  
  1141. /******************************************************************************/
  1142.  
  1143. DESTRUCTOR_P(SocketExit,501)
  1144. {
  1145.     ENTER();
  1146.  
  1147.     SaveDescriptorCleanup();
  1148.     UnblockDescriptorCleanup();
  1149.     CloseUnlinkUnlockCleanup();
  1150.     ForbidDOSCleanup();
  1151.  
  1152.     LEAVE();
  1153. }
  1154.  
  1155. /******************************************************************************/
  1156.  
  1157. CONSTRUCTOR_P(DaemonInit,501)
  1158. {
  1159.     ENTER();
  1160.  
  1161.     DaemonInit();
  1162.  
  1163.     RETURN(0);
  1164.     return(0);
  1165. }
  1166.  
  1167. /******************************************************************************/
  1168.  
  1169. struct MangleInfo
  1170. {
  1171.     char    mi_Substitute[MAX_FILENAME_LEN];
  1172.     char *    mi_OldName;
  1173. };
  1174.  
  1175. STATIC VOID
  1176. UnmangleName(char ** namePtr,struct MangleInfo * mi)
  1177. {
  1178.     /* Reset the name pointer to its previous position. */
  1179.     (*namePtr) = mi->mi_OldName;
  1180. }
  1181.  
  1182. STATIC int
  1183. MangleName(char ** namePtr,struct MangleInfo * mi)
  1184. {
  1185.     char * name = (*namePtr);
  1186.     int result = ERROR;
  1187.  
  1188.     ENTER();
  1189.  
  1190.     if(TranslateRelativePath(&name,mi->mi_Substitute,sizeof(mi->mi_Substitute)) == OK)
  1191.     {
  1192.         char * replace = mi->mi_Substitute;
  1193.         int len,i;
  1194.  
  1195.         len = strlen(name);
  1196.  
  1197.         /* If there is one, strip the trailing slash. */
  1198.         if(len > 1 && name[len-1] == '/')
  1199.         {
  1200.             if(name != replace)
  1201.             {
  1202.                 strcpy(replace,name);
  1203.                 name = replace;
  1204.             }
  1205.  
  1206.             name[--len] = '\0';
  1207.         }
  1208.  
  1209.         if(strcmp(name,".") == SAME)
  1210.         {
  1211.             /* Convert to current directory. */
  1212.             name = "";
  1213.         }
  1214.         else if (strcmp(name,"..") == SAME)
  1215.         {
  1216.             /* Convert to parent directory. */
  1217.             name = "/";
  1218.         }
  1219.         else if (strncmp(name,"./",2) == SAME)
  1220.         {
  1221.             /* Retain just the name. */
  1222.             name += 2;
  1223.         }
  1224.         else if (strncmp(name,"../",3) == SAME)
  1225.         {
  1226.             /* Convert to parent directory. */
  1227.             name += 2;
  1228.         }
  1229.         else if (strncmp(name,"/",1) == SAME)
  1230.         {
  1231.             /* Ok, so this is an absolute path. We first
  1232.              * check for a few special cases, the first
  1233.              * being a reference to "/tmp".
  1234.              */
  1235.             if(Strnicmp(name,"/tmp",4) == SAME && (name[4] == '/' || name[4] == '\0'))
  1236.             {
  1237.                 if(name[4] == '/')
  1238.                 {
  1239.                     /* Convert "/tmp/foo" to "T:foo". */
  1240.                     strcpy(replace,"T:");
  1241.                     memmove(&replace[2],&name[5],strlen(&name[5])+1);
  1242.                 }
  1243.                 else
  1244.                 {
  1245.                     /* Convert "/tmp" to "T:". */
  1246.                     strcpy(replace,"T:");
  1247.                 }
  1248.  
  1249.                 name = replace;
  1250.             }
  1251.             else if(Strnicmp(name,"/dev/",5) == SAME)
  1252.             {
  1253.                 /* Except for "/dev/null" all references to
  1254.                  * files in "/dev" are redirected to nonexistant
  1255.                  * files. Note that this relies upon the fact
  1256.                  * that "NIL:" is not a true device.
  1257.                  */
  1258.                 if(Stricmp(name,"/dev/null") == SAME)
  1259.                     name = "NIL:";
  1260.                 else
  1261.                     name = "NIL:this_file_never_opens";
  1262.             }
  1263.             else
  1264.             {
  1265.                 int i,rest = 0,len = 0;
  1266.  
  1267.                 /* Find out how long the first component
  1268.                  * of the absolute path is.
  1269.                  */
  1270.                 for(i = 1 ; i <= strlen(name) ; i++)
  1271.                 {
  1272.                     if(name[i] == '/' || name[i] == '\0')
  1273.                     {
  1274.                         len = i-1;
  1275.  
  1276.                         /* Is there anything following
  1277.                          * the path name?
  1278.                          */
  1279.                         if(name[i] == '/')
  1280.                             rest = i+1;
  1281.  
  1282.                         break;
  1283.                     }
  1284.                 }
  1285.  
  1286.                 /* Copy the first component and
  1287.                  * attach a colon. "/foo" becomes
  1288.                  * "foo:" (without the trailing NUL
  1289.                  * byte, this will get attached
  1290.                  * later).
  1291.                  */
  1292.                 memmove(replace,&name[1],len);
  1293.                 replace[len++] = ':';
  1294.  
  1295.                 /* Now add the finishing touches. "/foo/bar" finally
  1296.                  * becomes "foo:bar" and "/foo" becomes "foo:" with the
  1297.                  * trailing NUL byte attached.
  1298.                  */
  1299.                 if(rest > 0)
  1300.                     memmove(&replace[len],&name[rest],strlen(&name[rest])+1);
  1301.                 else
  1302.                     replace[len] = '\0';
  1303.  
  1304.                 name = replace;
  1305.             }
  1306.         }
  1307.  
  1308.         /* Convert any "./" or "../" embedded in the name
  1309.          * if necessary.
  1310.          */
  1311.         for(i = 0 ; i < strlen(name) ; i++)
  1312.         {
  1313.             if(strncmp(&name[i],"./",2) == SAME ||
  1314.                strncmp(&name[i],"../",3) == SAME)
  1315.             {
  1316.                 char * from    = name;
  1317.                 char * to    = replace;
  1318.  
  1319.                 name = replace;
  1320.  
  1321.                 while((*from) != '\0')
  1322.                 {
  1323.                     if((*from) == '.')
  1324.                     {
  1325.                         if(from[1] == '/' || from[1] == '\0')
  1326.                         {
  1327.                             /* "."  -> "" (done)
  1328.                              * "./" -> "" (continue)
  1329.                              */
  1330.                             if(from[1] == '\0')
  1331.                                 break;
  1332.                             else
  1333.                                 from += 2;
  1334.                         }
  1335.                         else if (from[1] == '.' && (from[2] == '/' || from[2] == '\0'))
  1336.                         {
  1337.                             /* ".."  -> "/" (done)
  1338.                              * "../" -> "/" (continue)
  1339.                              */
  1340.                             (*to++) = '/';
  1341.  
  1342.                             if(from[2] == '\0')
  1343.                                 break;
  1344.                             else
  1345.                                 from += 3;
  1346.                         }
  1347.                         else
  1348.                         {
  1349.                             (*to++) = (*from++);
  1350.                         }
  1351.                     }
  1352.                     else
  1353.                     {
  1354.                         (*to++) = (*from++);
  1355.                     }
  1356.                 }
  1357.  
  1358.                 (*to) = '\0';
  1359.  
  1360.                 break;
  1361.             }
  1362.         }
  1363.  
  1364.         /* Reduce any "//" embedded in the name if
  1365.          * necessary.
  1366.          */
  1367.         for(i = 0 ; i < strlen(name)-1 ; i++)
  1368.         {
  1369.             if(name[i] == '/' && name[i+1] == '/')
  1370.             {
  1371.                 int position,len;
  1372.  
  1373.                 if(name != replace)
  1374.                 {
  1375.                     strcpy(replace,name);
  1376.                     name = replace;
  1377.                 }
  1378.  
  1379.                 len = strlen(name);
  1380.  
  1381.                 position = len - 1;
  1382.                 while(position > 1 && name[position] != ':')
  1383.                 {
  1384.                     /* "foo/bar//baz" -> "foo/baz" */
  1385.                     if(name[position] == '/' && name[position-1] == '/')
  1386.                     {
  1387.                         int componentLen;
  1388.  
  1389.                         /* Move in front of the name component preceding the "//". */
  1390.                         componentLen = 0;
  1391.                         for(i = position - 2 ; i > 0 && name[i] != ':' && name[i] != '/' ; i--)
  1392.                             componentLen++;
  1393.  
  1394.                         if(componentLen > 0)
  1395.                         {
  1396.                             memmove(&name[position - (componentLen + 1)],&name[position + 1],len - (position + 1));
  1397.  
  1398.                             len -= componentLen + 2;
  1399.                             name[len] = '\0';
  1400.  
  1401.                             position -= componentLen + 1;
  1402.                         }
  1403.                     }
  1404.  
  1405.                     position--;
  1406.                 }
  1407.  
  1408.                 break;
  1409.             }
  1410.         }
  1411.  
  1412.         D(("original name |%s|",(*namePtr)));
  1413.         D((" mangled name |%s|",name));
  1414.  
  1415.         /* Look for extra colon characters
  1416.          * embedded in the name (as in "foo:bar:baz"
  1417.          * or "foo/bar:baz") which really don't
  1418.          * belong here.
  1419.          */
  1420.         len = strlen(name);
  1421.         for(i = 0 ; i < len ; i++)
  1422.         {
  1423.             if(name[i] == ':' || name[i] == '/')
  1424.             {
  1425.                 int j;
  1426.  
  1427.                 for(j = i+1 ; j < len ; j++)
  1428.                 {
  1429.                     if(name[j] == ':')
  1430.                     {
  1431.                         errno = EINVAL; /* invalid name */
  1432.                         goto out;
  1433.                     }
  1434.                 }
  1435.  
  1436.                 break;
  1437.             }
  1438.         }
  1439.  
  1440.         /* Now check if the file name is longer than the
  1441.          * maximum supported by the ROM file system. This
  1442.          * is to avoid name space clashes.
  1443.          */
  1444.         if(strlen(FilePart((STRPTR)name)) > MAX_FFS_NAME_LEN)
  1445.         {
  1446.             LONG error = OK;
  1447.             BPTR fileLock;
  1448.  
  1449.             /* This is a tricky issue: the filing system we are talking
  1450.              * to may be able to handle more than 30 characters, but then
  1451.              * it may be not, it's impossible to tell. We adopt the following
  1452.              * strategy: we try to access the named file and compare its
  1453.              * name against the one reported by the file system. If the name
  1454.              * reported by the file system is shorter than the one provided,
  1455.              * but matches it otherwise, we will assume that trouble is underway
  1456.              * and back out backwards.
  1457.              */
  1458.  
  1459.             ForbidDOS();
  1460.  
  1461.             fileLock = Lock((STRPTR)name,SHARED_LOCK);
  1462.             if(fileLock != ZERO)
  1463.             {
  1464.                 struct FileInfoBlock __aligned fib;
  1465.  
  1466.                 if(Examine(fileLock,&fib))
  1467.                 {
  1468.                     int len;
  1469.  
  1470.                     /* Now check if the name reported by the
  1471.                      * filing system is shorter than the
  1472.                      * one we asked for, but matches otherwise.
  1473.                      */
  1474.                     len = strlen(fib.fib_FileName);
  1475.                     if(strlen((STRPTR)name) > len && Strnicmp((STRPTR)name,fib.fib_FileName,len) == SAME)
  1476.                     {
  1477.                         /* The name is too long to handle. */
  1478.                         error = ERROR_LINE_TOO_LONG;
  1479.                     }
  1480.                 }
  1481.                 else
  1482.                 {
  1483.                     error = IoErr();
  1484.                 }
  1485.  
  1486.                 UnLock(fileLock);
  1487.             }
  1488.             else
  1489.             {
  1490.                 error = IoErr();
  1491.             }
  1492.  
  1493.             PermitDOS();
  1494.  
  1495.             /* We don't complain if the file does
  1496.              * not exist, but if it is currently in
  1497.              * use, on a volume that's not currently
  1498.              * mounted, etc. we will complain.
  1499.              */
  1500.             if(error != OK && error != ERROR_OBJECT_NOT_FOUND)
  1501.             {
  1502.                 SetIoErr(error);
  1503.                 MapIoErrToErrno();
  1504.  
  1505.                 goto out;
  1506.             }
  1507.         }
  1508.  
  1509.         mi->mi_OldName = (*namePtr);
  1510.         (*namePtr) = name;
  1511.  
  1512.         result = OK;
  1513.     }
  1514.  
  1515. out:
  1516.  
  1517.     RETURN(result);
  1518.     return(result);
  1519. }
  1520.  
  1521. /******************************************************************************/
  1522.  
  1523. STATIC int MaxOpenDescriptor = -1;
  1524.  
  1525. STATIC VOID
  1526. CloseUnlinkUnlockCleanup(VOID)
  1527. {
  1528.     struct UFB * ufb;
  1529.     int fd;
  1530.  
  1531.     ForbidDOS();
  1532.  
  1533.     /* Don't let anybody stop us. */
  1534.     signal(SIGINT,SIG_IGN);
  1535.     signal(SIGTERM,SIG_IGN);
  1536.  
  1537.     /* We look for descriptors we marked for
  1538.      * deletion.
  1539.      */
  1540.     for(fd = 0 ; fd <= MaxOpenDescriptor ; fd++)
  1541.     {
  1542.         CleanupFileLocks(fd);
  1543.  
  1544.         ufb = chkufb(fd);
  1545.         if(ufb != NULL && FLAG_IS_SET(ufb->ufbflg,UFB_UNLINK))
  1546.         {
  1547.             char fileName[MAX_FILENAME_LEN];
  1548.             BOOL removeIt;
  1549.  
  1550.             removeIt = NameFromFH((BPTR)ufb->ufbfh,fileName,sizeof(fileName));
  1551.  
  1552.             CLEAR_FLAG(ufb->ufbflg,UFB_UNLINK);
  1553.  
  1554.             close(fd);
  1555.  
  1556.             if(removeIt)
  1557.                 DeleteFile(fileName);
  1558.         }
  1559.     }
  1560.  
  1561.     PermitDOS();
  1562. }
  1563.  
  1564. int
  1565. amiga_unlink(char *name)
  1566. {
  1567.     struct MangleInfo mi;
  1568.     BPTR fileLock;
  1569.     int result = ERROR;
  1570.  
  1571.     chkabort();
  1572.  
  1573.     ASSERT(name != NULL);
  1574.  
  1575.     ENTER();
  1576.     SHOWSTRING(name);
  1577.  
  1578.     if(MangleName(&name,&mi) == OK)
  1579.     {
  1580.         LONG error = OK;
  1581.  
  1582.         ForbidDOS();
  1583.  
  1584.         fileLock = Lock(name,SHARED_LOCK);
  1585.         if(fileLock != ZERO)
  1586.         {
  1587.             struct FileInfoBlock __aligned fib;
  1588.  
  1589.             if(Examine(fileLock,&fib))
  1590.             {
  1591.                 UnLock(fileLock);
  1592.                 fileLock = ZERO;
  1593.  
  1594.                 /* Make sure that we get to remove
  1595.                  * a file, as the name implies.
  1596.                  */
  1597.                 if(FIB_IS_FILE(&fib))
  1598.                 {
  1599.                     if(DeleteFile(name))
  1600.                         result = OK;
  1601.                     else
  1602.                         error = IoErr();
  1603.                 }
  1604.                 else
  1605.                 {
  1606.                     errno = EISDIR;
  1607.                 }
  1608.             }
  1609.             else
  1610.             {
  1611.                 error = IoErr();
  1612.             }
  1613.  
  1614.             UnLock(fileLock);
  1615.         }
  1616.         else
  1617.         {
  1618.             error = IoErr();
  1619.         }
  1620.  
  1621.         PermitDOS();
  1622.  
  1623.         /* Check if we couldn't delete the file in
  1624.          * question because there still is a file
  1625.          * handle attached to it. If we can find that
  1626.          * file, we will mark it for deletion lateron
  1627.          * when the file is closed.
  1628.          */
  1629.         if(result != OK && error == ERROR_OBJECT_IN_USE)
  1630.         {
  1631.             char parentDirName[MAX_FILENAME_LEN];
  1632.             BOOL foundParentDirName;
  1633.             BPTR fileParentDir;
  1634.             int i;
  1635.  
  1636.             ASSERT(strlen(name) < sizeof(parentDirName));
  1637.  
  1638.             strcpy(parentDirName,name);
  1639.             foundParentDirName = FALSE;
  1640.  
  1641.             for(i = strlen(parentDirName)-1 ; i >= 0 ; i--)
  1642.             {
  1643.                 if(parentDirName[i] == ':')
  1644.                 {
  1645.                     if(parentDirName[i+1] != '\0')
  1646.                     {
  1647.                         parentDirName[i+1] = '\0';
  1648.                         foundParentDirName = TRUE;
  1649.                     }
  1650.  
  1651.                     break;
  1652.                 }
  1653.                 else if (parentDirName[i] == '/')
  1654.                 {
  1655.                     parentDirName[i] = '\0';
  1656.                     foundParentDirName = TRUE;
  1657.                     break;
  1658.                 }
  1659.             }
  1660.  
  1661.             /* Did we find this file's parent directory name? */
  1662.             if(foundParentDirName)
  1663.             {
  1664.                 D(("locking |%s|",parentDirName));
  1665.  
  1666.                 /* Get a lock on the file's parent directory. */
  1667.                 fileParentDir = Lock(parentDirName,SHARED_LOCK);
  1668.                 if(fileParentDir != ZERO)
  1669.                 {
  1670.                     BPTR descriptorParentDir;
  1671.                     BOOL gotIt = FALSE;
  1672.                     struct UFB * ufb;
  1673.                     int fd;
  1674.  
  1675.                     for(fd = 0 ; fd <= MaxOpenDescriptor ; fd++)
  1676.                     {
  1677.                         ufb = chkufb(fd);
  1678.                         if(ufb != NULL && FLAG_IS_CLEAR(ufb->ufbflg,UFB_IS_SOCKET))
  1679.                         {
  1680.                             /* And also get a lock on the file
  1681.                              * descriptor's parent directory.
  1682.                              */
  1683.                             descriptorParentDir = ParentOfFH((BPTR)ufb->ufbfh);
  1684.                             if(descriptorParentDir != ZERO)
  1685.                             {
  1686.                                 /* Are the two pointing to the same drawer? */
  1687.                                 if(SameLock(fileParentDir,descriptorParentDir) == LOCK_SAME)
  1688.                                 {
  1689.                                     struct FileInfoBlock __aligned fib;
  1690.  
  1691.                                     if(ExamineFH((BPTR)ufb->ufbfh,&fib))
  1692.                                     {
  1693.                                         /* Check if the two share the same name. */
  1694.                                         if(Stricmp(fib.fib_FileName,FilePart(name)) == SAME)
  1695.                                         {
  1696.                                             /* Mark this file for deletion. */
  1697.                                             SET_FLAG(ufb->ufbflg,UFB_UNLINK);
  1698.  
  1699.                                             gotIt = TRUE;
  1700.                                             error = OK;
  1701.                                             result = OK;
  1702.                                         }
  1703.                                     }
  1704.                                     else
  1705.                                     {
  1706.                                         SHOWMSG("couldn't examine the descriptor");
  1707.                                     }
  1708.                                 }
  1709.                                 else
  1710.                                 {
  1711.                                     SHOWMSG("file and descriptor don't live in the same drawer");
  1712.                                 }
  1713.  
  1714.                                 UnLock(descriptorParentDir);
  1715.                             }
  1716.                             else
  1717.                             {
  1718.                                 SHOWMSG("the descriptor doesn't have a parent directory (huh?!?)");
  1719.                             }
  1720.                         }
  1721.  
  1722.                         if(gotIt)
  1723.                             break;
  1724.                     }
  1725.  
  1726.                     UnLock(fileParentDir);
  1727.                 }
  1728.                 else
  1729.                 {
  1730.                     D(("couldn't get a lock on |%s|",parentDirName));
  1731.                 }
  1732.             }
  1733.             else
  1734.             {
  1735.                 D(("didn't find parent dir name of |%s|",name));
  1736.             }
  1737.         }
  1738.  
  1739.         /* Take care of the AmigaDOS error
  1740.          * code, if there is any.
  1741.          */
  1742.         if(result != OK && error != OK)
  1743.         {
  1744.             SetIoErr(error);
  1745.             MapIoErrToErrno();
  1746.         }
  1747.  
  1748.         UnmangleName(&name,&mi);
  1749.     }
  1750.  
  1751.     RETURN(result);
  1752.     return(result);
  1753. }
  1754.  
  1755. int
  1756. amiga_open(char *name,int mode,int prot)
  1757. {
  1758.     struct MangleInfo mi;
  1759.     int result = ERROR;
  1760.  
  1761.     chkabort();
  1762.  
  1763.     ASSERT(name != NULL);
  1764.  
  1765.     ENTER();
  1766.     SHOWSTRING(name);
  1767.     SHOWVALUE(mode);
  1768.     SHOWVALUE(prot);
  1769.  
  1770.     if(MangleName(&name,&mi) == OK)
  1771.     {
  1772.         /* Clear the "no delay" flag since the SAS/C
  1773.          * runtime library does not support it.
  1774.          */
  1775.         CLEAR_FLAG(mode,O_NONBLOCK);
  1776.  
  1777.         ForbidDOS();
  1778.  
  1779.         result = open(name,mode,prot);
  1780.         if(result != ERROR && MaxOpenDescriptor < result)
  1781.             MaxOpenDescriptor = result;
  1782.  
  1783.         PermitDOS();
  1784.  
  1785.         UnmangleName(&name,&mi);
  1786.     }
  1787.  
  1788.     RETURN(result);
  1789.     return(result);
  1790. }
  1791.  
  1792. /******************************************************************************/
  1793.  
  1794. STATIC char CurrentDirName[MAX_FILENAME_LEN] = "";
  1795.  
  1796. int
  1797. amiga_chdir(char *path)
  1798. {
  1799.     BOOL isAbsolutePath;
  1800.     struct MangleInfo mi;
  1801.     int result = ERROR;
  1802.  
  1803.     chkabort();
  1804.  
  1805.     ASSERT(path != NULL);
  1806.  
  1807.     ENTER();
  1808.     SHOWSTRING(path);
  1809.  
  1810.     /* Is this an absolute path? */
  1811.     isAbsolutePath = (BOOL)(path[0] == '/');
  1812.  
  1813.     if(MangleName(&path,&mi) == OK)
  1814.     {
  1815.         BPTR drawerLock;
  1816.  
  1817.         D(("chdir(\"%s\")",path));
  1818.  
  1819.         ForbidDOS();
  1820.  
  1821.         drawerLock = Lock(path,SHARED_LOCK);
  1822.         if(drawerLock != ZERO)
  1823.         {
  1824.             struct FileInfoBlock __aligned fib;
  1825.  
  1826.             if(Examine(drawerLock,&fib))
  1827.             {
  1828.                 /* We can only move into drawers. */
  1829.                 if(FIB_IS_DRAWER(&fib))
  1830.                 {
  1831.                     /* If necessary, get the name of
  1832.                      * the drawer to move into.
  1833.                      */
  1834.                     if(NOT isAbsolutePath)
  1835.                     {
  1836.                         UBYTE localName[MAX_FILENAME_LEN];
  1837.  
  1838.                         if(NameFromLock(drawerLock,localName,sizeof(localName)))
  1839.                             result = MapFileNameAmigaToUnix(localName,CurrentDirName,sizeof(CurrentDirName));
  1840.                         else
  1841.                             MapIoErrToErrno();
  1842.                     }
  1843.                     else
  1844.                     {
  1845.                         result = OK;
  1846.                     }
  1847.  
  1848.                     /* If everything went well,
  1849.                      * move into the drawer.
  1850.                      */
  1851.                     if(result == OK)
  1852.                     {
  1853.                         BPTR oldDrawer;
  1854.  
  1855.                         oldDrawer = CurrentDir(drawerLock);
  1856.  
  1857.                         /* Unlock the old drawer we came from
  1858.                          * unless we want to return to it
  1859.                          * when the program exits.
  1860.                          */
  1861.                         if(InitialCurrentDirInitialized)
  1862.                         {
  1863.                             UnLock(oldDrawer);
  1864.                         }
  1865.                         else
  1866.                         {
  1867.                             InitialCurrentDir = oldDrawer;
  1868.                             InitialCurrentDirInitialized = TRUE;
  1869.                         }
  1870.  
  1871.                         /* Make sure that this drawer is going
  1872.                          * to be unlocked when the program exits.
  1873.                          */
  1874.                         ChangedCurrentDir = drawerLock;
  1875.                     }
  1876.                 }
  1877.                 else
  1878.                 {
  1879.                     errno = ENOTDIR;
  1880.                 }
  1881.             }
  1882.             else
  1883.             {
  1884.                 MapIoErrToErrno();
  1885.             }
  1886.  
  1887.             if(result != OK)
  1888.                 UnLock(drawerLock);
  1889.         }
  1890.         else
  1891.         {
  1892.             MapIoErrToErrno();
  1893.         }
  1894.  
  1895.         PermitDOS();
  1896.  
  1897.         UnmangleName(&path,&mi);
  1898.  
  1899.         if(result == OK && isAbsolutePath)
  1900.             strcpy(CurrentDirName,path);
  1901.     }
  1902.  
  1903.     RETURN(result);
  1904.     return(result);
  1905. }
  1906.  
  1907. /******************************************************************************/
  1908.  
  1909. struct OpenDirNode
  1910. {
  1911.     struct MinNode            odn_MinNode;
  1912.     BPTR                    odn_FileLock;
  1913.     struct FileInfoBlock    odn_FIB;
  1914.     struct List                odn_VolumeList;
  1915.     DIR                        odn_DIR;
  1916.     BOOL                    odn_ReadingVolumes;
  1917.     struct dirent            odn_DirectoryEntry;
  1918.     struct Node *            odn_NextNode;
  1919.     ULONG                    odn_NextDirEntryIndex;
  1920.     LONG                    odn_ParentDirKey;
  1921. };
  1922.  
  1923. STATIC struct List OpenDirList;
  1924. STATIC BOOL OpenDirListInitialized = FALSE;
  1925.  
  1926. STATIC ULONG RootBlocks = 0;
  1927. STATIC ULONG RootBlocksUsed = 0;
  1928.  
  1929. STATIC VOID
  1930. OpenDirCleanup(VOID)
  1931. {
  1932.     struct OpenDirNode * odn;
  1933.  
  1934.     /* Unlock all directories still being scanned
  1935.      * when exit() was called.
  1936.      */
  1937.     for(odn = (struct OpenDirNode *)OpenDirList.lh_Head ;
  1938.         odn->odn_MinNode.mln_Succ != NULL ;
  1939.         odn = (struct OpenDirNode *)odn->odn_MinNode.mln_Succ)
  1940.     {
  1941.         UnLock(odn->odn_FileLock);
  1942.     }
  1943. }
  1944.  
  1945. DIR *
  1946. amiga_opendir(char *dirName)
  1947. {
  1948.     char localDirName[MAX_FILENAME_LEN];
  1949.     DIR *result = NULL;
  1950.  
  1951.     chkabort();
  1952.  
  1953.     ASSERT(dirName != NULL);
  1954.  
  1955.     ENTER();
  1956.  
  1957.     SHOWSTRING(dirName);
  1958.  
  1959.     /* Make sure that the directory list is
  1960.      * set up properly.
  1961.      */
  1962.     if(NOT OpenDirListInitialized)
  1963.     {
  1964.         NewList(&OpenDirList);
  1965.         OpenDirListInitialized = TRUE;
  1966.         atexit(OpenDirCleanup);
  1967.     }
  1968.  
  1969.     if(TranslateRelativePath(&dirName,localDirName,sizeof(localDirName)) == OK)
  1970.     {
  1971.         /* Check if we are to scan the virtual root directory. */
  1972.         if(strcmp(dirName,"/") == SAME)
  1973.         {
  1974.             struct OpenDirNode * odn;
  1975.  
  1976.             odn = malloc(sizeof(*odn));
  1977.             if(odn != NULL)
  1978.             {
  1979.                 struct DosList * dol;
  1980.  
  1981.                 RootBlocks = RootBlocksUsed = 0;
  1982.  
  1983.                 memset(odn,0,sizeof(*odn));
  1984.                 odn->odn_ReadingVolumes = TRUE;
  1985.                 odn->odn_DIR.dd_buf = (char *)odn;
  1986.                 NewList(&odn->odn_VolumeList);
  1987.  
  1988.                 AddHead(&OpenDirList,(struct Node *)odn);
  1989.  
  1990.                 result = &odn->odn_DIR;
  1991.  
  1992.                 /* Now collect all volumes in the system. */
  1993.                 dol = NextDosEntry(LockDosList(LDF_VOLUMES|LDF_READ),
  1994.                                                LDF_VOLUMES|LDF_READ);
  1995.                 while(dol != NULL)
  1996.                 {
  1997.                     /* Does the volume refer to a medium that is right
  1998.                      * now present in the drive?
  1999.                      */
  2000.                     if(dol->dol_Task != NULL)
  2001.                     {
  2002.                         struct InfoData __aligned id;
  2003.  
  2004.                         /* Is there a disk present? */
  2005.                         if(DoPkt(dol->dol_Task,ACTION_DISK_INFO,MKBADDR(&id),    0,0,0,0))
  2006.                         {
  2007.                             STRPTR name = BADDR(dol->dol_Name);
  2008.                             struct Node * node;
  2009.  
  2010.                             /* Collect the number of blocks used and
  2011.                              * available in our fake root directory.
  2012.                              * Not that it matters much...
  2013.                              */
  2014.                             if(id.id_BytesPerBlock == 512)
  2015.                             {
  2016.                                 RootBlocks        += id.id_NumBlocks;
  2017.                                 RootBlocksUsed    += id.id_NumBlocksUsed;
  2018.                             }
  2019.                             else
  2020.                             {
  2021.                                 RootBlocks        += (id.id_NumBlocks * id.id_BytesPerBlock) / 512;
  2022.                                 RootBlocksUsed    += (id.id_NumBlocksUsed * id.id_BytesPerBlock) / 512;
  2023.                             }
  2024.  
  2025.                             node = malloc(sizeof(*node) + ((int)name[0])+1);
  2026.                             if(node != NULL)
  2027.                             {
  2028.                                 /* Copy the name of the volume. */
  2029.                                 node->ln_Name = (char *)(node + 1);
  2030.                                 strncpy(node->ln_Name,&name[1],name[0]);
  2031.                                 node->ln_Name[ name[0] ] = '\0';
  2032.  
  2033.                                 AddTail(&odn->odn_VolumeList,node);
  2034.  
  2035.                                 if(odn->odn_NextNode == NULL)
  2036.                                     odn->odn_NextNode = node;
  2037.                             }
  2038.                         }
  2039.                     }
  2040.  
  2041.                     dol = NextDosEntry(dol,LDF_VOLUMES|LDF_READ);
  2042.                 }
  2043.  
  2044.                 UnLockDosList(LDF_VOLUMES|LDF_READ);
  2045.             }
  2046.             else
  2047.             {
  2048.                 errno = ENOMEM;
  2049.             }
  2050.         }
  2051.         else
  2052.         {
  2053.             struct MangleInfo mi;
  2054.  
  2055.             if(MangleName(&dirName,&mi) == OK)
  2056.             {
  2057.                 BPTR fileLock;
  2058.  
  2059.                 ForbidDOS();
  2060.  
  2061.                 fileLock = Lock(dirName,SHARED_LOCK);
  2062.                 if(fileLock != ZERO)
  2063.                 {
  2064.                     struct OpenDirNode * odn;
  2065.  
  2066.                     odn = malloc(sizeof(*odn));
  2067.                     if(odn != NULL)
  2068.                     {
  2069.                         BPTR parentDir;
  2070.  
  2071.                         memset(odn,0,sizeof(*odn));
  2072.  
  2073.                         parentDir = ParentDir(fileLock);
  2074.                         if(parentDir != ZERO)
  2075.                         {
  2076.                             if(Examine(parentDir,&odn->odn_FIB))
  2077.                                 odn->odn_ParentDirKey = odn->odn_FIB.fib_DiskKey;
  2078.  
  2079.                             UnLock(parentDir);
  2080.                         }
  2081.  
  2082.                         if(Examine(fileLock,&odn->odn_FIB))
  2083.                         {
  2084.                             /* Make sure that we are
  2085.                              * trying to read a drawer
  2086.                              * and not a file.
  2087.                              */
  2088.                             if(FIB_IS_DRAWER(&odn->odn_FIB))
  2089.                             {
  2090.                                 odn->odn_DIR.dd_buf = (char *)odn;
  2091.                                 odn->odn_FileLock = fileLock;
  2092.                                 NewList(&odn->odn_VolumeList);
  2093.  
  2094.                                 /* The lock has been "swallowed"
  2095.                                  * by the dir node; make sure that
  2096.                                  * we don't unlock it.
  2097.                                  */
  2098.                                 fileLock = ZERO;
  2099.  
  2100.                                 AddHead(&OpenDirList,(struct Node *)odn);
  2101.                                 result = &odn->odn_DIR;
  2102.                             }
  2103.                             else
  2104.                             {
  2105.                                 errno = ENOTDIR;
  2106.                             }
  2107.                         }
  2108.                         else
  2109.                         {
  2110.                             MapIoErrToErrno();
  2111.                         }
  2112.  
  2113.                         if(result == NULL)
  2114.                             free(odn);
  2115.                     }
  2116.                     else
  2117.                     {
  2118.                         errno = ENOMEM;
  2119.                     }
  2120.  
  2121.                     UnLock(fileLock);
  2122.                 }
  2123.                 else
  2124.                 {
  2125.                     MapIoErrToErrno();
  2126.                 }
  2127.  
  2128.                 PermitDOS();
  2129.  
  2130.                 UnmangleName(&dirName,&mi);
  2131.             }
  2132.         }
  2133.     }
  2134.  
  2135.     RETURN(result);
  2136.     return(result);
  2137. }
  2138.  
  2139. VOID
  2140. amiga_closedir(DIR *dir)
  2141. {
  2142.     if(dir != NULL)
  2143.     {
  2144.         struct OpenDirNode * odn = (struct OpenDirNode *)dir->dd_buf;
  2145.  
  2146.         if(odn != NULL)
  2147.         {
  2148.             struct Node * node;
  2149.  
  2150.             Remove((struct Node *)odn);
  2151.  
  2152.             while((node = RemHead(&odn->odn_VolumeList)) != NULL)
  2153.                 free(node);
  2154.  
  2155.             UnLock(odn->odn_FileLock);
  2156.             free(odn);
  2157.         }
  2158.     }
  2159.  
  2160.     chkabort();
  2161. }
  2162.  
  2163. struct dirent *
  2164. amiga_readdir(DIR *dir)
  2165. {
  2166.     struct dirent * result = NULL;
  2167.  
  2168.     chkabort();
  2169.  
  2170.     if(dir != NULL)
  2171.     {
  2172.         struct OpenDirNode * odn = (struct OpenDirNode *)dir->dd_buf;
  2173.  
  2174.         if(odn != NULL)
  2175.         {
  2176.             struct dirent * d = &odn->odn_DirectoryEntry;
  2177.  
  2178.             if(odn->odn_ReadingVolumes)
  2179.             {
  2180.                 /* The first directory entry points
  2181.                  * back to the directory itself.
  2182.                  */
  2183.                 if(odn->odn_NextDirEntryIndex == 0)
  2184.                 {
  2185.                     strcpy(d->d_name,".");
  2186.  
  2187.                     d->d_ino    = ++odn->odn_NextDirEntryIndex;
  2188.                     d->d_namlen    = strlen(d->d_name);
  2189.  
  2190.                     result = d;
  2191.                 }
  2192.                 else
  2193.                 {
  2194.                     /* Return the next volume in the list. */
  2195.                     if(odn->odn_NextNode != NULL && odn->odn_NextNode->ln_Succ != NULL)
  2196.                     {
  2197.                         ASSERT(sizeof(d->d_name) >= strlen(odn->odn_NextNode->ln_Name));
  2198.  
  2199.                         strcpy(d->d_name,odn->odn_NextNode->ln_Name);
  2200.  
  2201.                         odn->odn_NextNode = odn->odn_NextNode->ln_Succ;
  2202.  
  2203.                         d->d_ino    = odn->odn_NextDirEntryIndex++;
  2204.                         d->d_namlen    = strlen(d->d_name);
  2205.  
  2206.                         result = d;
  2207.                     }
  2208.                     else
  2209.                     {
  2210.                         errno = 0;
  2211.                     }
  2212.                 }
  2213.             }
  2214.             else
  2215.             {
  2216.                 if(odn->odn_NextDirEntryIndex == 0)
  2217.                 {
  2218.                     /* The first directory entry points
  2219.                      * back to the directory itself.
  2220.                      */
  2221.                     strcpy(d->d_name,".");
  2222.  
  2223.                     d->d_ino    = odn->odn_FIB.fib_DiskKey;
  2224.                     d->d_namlen    = strlen(d->d_name);
  2225.  
  2226.                     odn->odn_NextDirEntryIndex++;
  2227.                     result = d;
  2228.                 }
  2229.                 else if(odn->odn_NextDirEntryIndex == 1)
  2230.                 {
  2231.                     /* The second directory entry points
  2232.                      * to the parent directory.
  2233.                      */
  2234.                     strcpy(d->d_name,"..");
  2235.  
  2236.                     d->d_ino    = odn->odn_ParentDirKey;
  2237.                     d->d_namlen    = strlen(d->d_name);
  2238.  
  2239.                     odn->odn_NextDirEntryIndex++;
  2240.                     result = d;
  2241.                 }
  2242.                 else
  2243.                 {
  2244.                     ForbidDOS();
  2245.  
  2246.                     /* All other iterations pick up the
  2247.                      * next following directory entry.
  2248.                      */
  2249.                     if(ExNext(odn->odn_FileLock,&odn->odn_FIB))
  2250.                     {
  2251.                         ASSERT(sizeof(d->d_name) >= strlen(odn->odn_FIB.fib_FileName));
  2252.  
  2253.                         strcpy(d->d_name,odn->odn_FIB.fib_FileName);
  2254.  
  2255.                         d->d_ino    = odn->odn_FIB.fib_DiskKey;
  2256.                         d->d_namlen    = strlen(d->d_name);
  2257.  
  2258.                         result = d;
  2259.                     }
  2260.                     else
  2261.                     {
  2262.                         LONG error = IoErr();
  2263.  
  2264.                         if(error == ERROR_NO_MORE_ENTRIES)
  2265.                         {
  2266.                             errno = 0;
  2267.                         }
  2268.                         else
  2269.                         {
  2270.                             SetIoErr(error);
  2271.                             MapIoErrToErrno();
  2272.                         }
  2273.                     }
  2274.  
  2275.                     PermitDOS();
  2276.                 }
  2277.             }
  2278.         }
  2279.     }
  2280.  
  2281.     if(result != NULL)
  2282.         SHOWSTRING(result->d_name);
  2283.  
  2284.     return(result);
  2285. }
  2286.  
  2287. /******************************************************************************/
  2288.  
  2289. STATIC int
  2290. TranslateRelativePath(char **namePtr,char *replace,int maxReplaceLen)
  2291. {
  2292.     int result = ERROR;
  2293.     char * name;
  2294.  
  2295.     ASSERT(namePtr != NULL && (*namePtr) != NULL && replace != NULL);
  2296.  
  2297.     /* If we have a current directory all references should
  2298.      * be made relative to, do just that. Absolute paths
  2299.      * are not modified, though.
  2300.      */
  2301.     name = (*namePtr);
  2302.     if(NOT STRING_IS_EMPTY(CurrentDirName) && name[0] != '/')
  2303.     {
  2304.         int totalLen;
  2305.  
  2306.         SHOWMSG("Changing the directory name");
  2307.  
  2308.         /* Skip current dir modifiers, we just want the name. */
  2309.         if(strncmp(name,"./",2) == SAME)
  2310.             name += 2;
  2311.         else if (strcmp(name,".") == SAME)
  2312.             name = "";
  2313.  
  2314.         /* Get the current directory name and get
  2315.          * ready to attach the file name at the end.
  2316.          */
  2317.         totalLen = strlen(CurrentDirName);
  2318.  
  2319.         if(CurrentDirName[strlen(CurrentDirName)-1] != '/' &&
  2320.            CurrentDirName[strlen(CurrentDirName)-1] != ':' &&
  2321.            NOT STRING_IS_EMPTY(name))
  2322.         {
  2323.             totalLen++;
  2324.         }
  2325.  
  2326.         totalLen += strlen(name);
  2327.  
  2328.         /* Check if the complete string will fit. */
  2329.         if(totalLen < maxReplaceLen)
  2330.         {
  2331.             /* Put the file name together. */
  2332.             strcpy(replace,CurrentDirName);
  2333.             if(CurrentDirName[strlen(CurrentDirName)-1] != '/' && NOT STRING_IS_EMPTY(name))
  2334.                 strcat(replace,"/");
  2335.  
  2336.             strcat(replace,name);
  2337.  
  2338.             (*namePtr) = replace;
  2339.             SHOWSTRING(*namePtr);
  2340.  
  2341.             result = OK;
  2342.         }
  2343.         else
  2344.         {
  2345.             errno = ENAMETOOLONG;
  2346.         }
  2347.     }
  2348.     else
  2349.     {
  2350.         result = OK;
  2351.     }
  2352.  
  2353.     return(result);
  2354. }
  2355.  
  2356. /******************************************************************************/
  2357.  
  2358. int
  2359. amiga_mkdir(char *name,int mode)
  2360. {
  2361.     struct MangleInfo mi;
  2362.     BPTR dirLock;
  2363.     int result = ERROR;
  2364.  
  2365.     chkabort();
  2366.  
  2367.     ASSERT(name != NULL);
  2368.  
  2369.     ENTER();
  2370.     SHOWSTRING(name);
  2371.     SHOWVALUE(mode);
  2372.  
  2373.     if(MangleName(&name,&mi) == OK)
  2374.     {
  2375.         ForbidDOS();
  2376.  
  2377.         dirLock = CreateDir((STRPTR)name);
  2378.         if(dirLock != ZERO)
  2379.         {
  2380.             UnLock(dirLock);
  2381.             result = OK;
  2382.         }
  2383.         else
  2384.         {
  2385.             MapIoErrToErrno();
  2386.         }
  2387.  
  2388.         PermitDOS();
  2389.  
  2390.         UnmangleName(&name,&mi);
  2391.     }
  2392.  
  2393.     if(result == OK)
  2394.         result = amiga_chmod(name,mode);
  2395.  
  2396.     RETURN(result);
  2397.     return(result);
  2398. }
  2399.  
  2400. /******************************************************************************/
  2401.  
  2402. int
  2403. amiga_rmdir(char *name)
  2404. {
  2405.     struct MangleInfo mi;
  2406.     BPTR fileLock;
  2407.     int result = ERROR;
  2408.  
  2409.     chkabort();
  2410.  
  2411.     ENTER();
  2412.     SHOWSTRING(name);
  2413.  
  2414.     if(MangleName(&name,&mi) == OK)
  2415.     {
  2416.         ForbidDOS();
  2417.  
  2418.         fileLock = Lock(name,SHARED_LOCK);
  2419.         if(fileLock != ZERO)
  2420.         {
  2421.             struct FileInfoBlock __aligned fib;
  2422.  
  2423.             if(Examine(fileLock,&fib))
  2424.             {
  2425.                 UnLock(fileLock);
  2426.                 fileLock = ZERO;
  2427.  
  2428.                 /* Make sure that we get to remove a drawer,
  2429.                  * as the function name implies.
  2430.                  */
  2431.                 if(FIB_IS_DRAWER(&fib))
  2432.                 {
  2433.                     if(DeleteFile(name))
  2434.                         result = OK;
  2435.                     else
  2436.                         MapIoErrToErrno();
  2437.                 }
  2438.                 else
  2439.                 {
  2440.                     errno = ENOTDIR;
  2441.                 }
  2442.             }
  2443.             else
  2444.             {
  2445.                 MapIoErrToErrno();
  2446.             }
  2447.  
  2448.             UnLock(fileLock);
  2449.         }
  2450.         else
  2451.         {
  2452.             MapIoErrToErrno();
  2453.         }
  2454.  
  2455.         PermitDOS();
  2456.  
  2457.         UnmangleName(&name,&mi);
  2458.     }
  2459.  
  2460.     RETURN(result);
  2461.     return(result);
  2462. }
  2463.  
  2464. /******************************************************************************/
  2465.  
  2466. int
  2467. amiga_creat(char *name,int prot)
  2468. {
  2469.     struct MangleInfo mi;
  2470.     int result = ERROR;
  2471.  
  2472.     chkabort();
  2473.  
  2474.     ASSERT(name != NULL);
  2475.  
  2476.     ENTER();
  2477.     SHOWSTRING(name);
  2478.     SHOWVALUE(prot);
  2479.  
  2480.     if(MangleName(&name,&mi) == OK)
  2481.     {
  2482.         ForbidDOS();
  2483.         result = creat(name,prot);
  2484.         PermitDOS();
  2485.  
  2486.         UnmangleName(&name,&mi);
  2487.     }
  2488.  
  2489.     RETURN(result);
  2490.     return(result);
  2491. }
  2492.  
  2493. /******************************************************************************/
  2494.  
  2495. FILE *
  2496. amiga_fopen(char *name,char *mode)
  2497. {
  2498.     struct MangleInfo mi;
  2499.     FILE *result = NULL;
  2500.  
  2501.     chkabort();
  2502.  
  2503.     ASSERT(name != NULL && mode != NULL);
  2504.  
  2505.     ENTER();
  2506.     SHOWSTRING(name);
  2507.     SHOWSTRING(mode);
  2508.  
  2509.     if(MangleName(&name,&mi) == OK)
  2510.     {
  2511.         ForbidDOS();
  2512.         result = fopen(name,mode);
  2513.         PermitDOS();
  2514.  
  2515.         UnmangleName(&name,&mi);
  2516.     }
  2517.  
  2518.     RETURN(result);
  2519.     return(result);
  2520. }
  2521.  
  2522. /******************************************************************************/
  2523.  
  2524. int
  2525. amiga_rename(char *old,char *new)
  2526. {
  2527.     struct MangleInfo old_mi;
  2528.     struct MangleInfo new_mi;
  2529.     int result = ERROR;
  2530.  
  2531.     chkabort();
  2532.  
  2533.     ASSERT(old != NULL && new != NULL);
  2534.  
  2535.     ENTER();
  2536.     SHOWSTRING(old);
  2537.     SHOWSTRING(new);
  2538.  
  2539.     /* rename() causes the link named <from> to be renamed as <to>. If <to> exists,
  2540.      * it is first removed. Both <from> and <to> must be of the same type (that is,
  2541.      * both directories or both non-directories), and must reside on the same
  2542.      * file system.
  2543.      */
  2544.  
  2545.     if(MangleName(&old,&old_mi) == OK)
  2546.     {
  2547.         if(MangleName(&new,&new_mi) == OK)
  2548.         {
  2549.             ForbidDOS();
  2550.  
  2551.             D(("rename |%s| to |%s|",old,new));
  2552.  
  2553.             if(CANNOT Rename(old,new))
  2554.             {
  2555.                 LONG error = IoErr();
  2556.  
  2557.                 SHOWVALUE(error);
  2558.  
  2559.                 if(error == ERROR_OBJECT_EXISTS)
  2560.                 {
  2561.                     BPTR oldLock = Lock(old,SHARED_LOCK);
  2562.                     BPTR newLock = Lock(new,SHARED_LOCK);
  2563.  
  2564.                     if(oldLock != ZERO && newLock != ZERO && SameLock(oldLock,newLock) == LOCK_SAME)
  2565.                     {
  2566.                         result = OK;
  2567.                         error = OK;
  2568.  
  2569.                         SHOWMSG("Ok; same name");
  2570.  
  2571.                         UnLock(oldLock);
  2572.                         UnLock(newLock);
  2573.                     }
  2574.                     else
  2575.                     {
  2576.                         UnLock(oldLock);
  2577.                         UnLock(newLock);
  2578.  
  2579.                         if(DeleteFile(new))
  2580.                         {
  2581.                             if(Rename(old,new))
  2582.                             {
  2583.                                 result = OK;
  2584.                                 error = OK;
  2585.  
  2586.                                 SHOWMSG("Ok; after removing");
  2587.                             }
  2588.                             else
  2589.                             {
  2590.                                 error = IoErr();
  2591.                             }
  2592.                         }
  2593.                         else
  2594.                         {
  2595.                             error = IoErr();
  2596.                         }
  2597.                     }
  2598.                 }
  2599.  
  2600.                 if(error != OK)
  2601.                 {
  2602.                     SHOWVALUE(error);
  2603.  
  2604.                     SetIoErr(error);
  2605.                     MapIoErrToErrno();
  2606.                 }
  2607.             }
  2608.             else
  2609.             {
  2610.                 SHOWMSG("Ok");
  2611.  
  2612.                 result = OK;
  2613.             }
  2614.  
  2615.             PermitDOS();
  2616.  
  2617.             UnmangleName(&new,&new_mi);
  2618.         }
  2619.         else
  2620.         {
  2621.             SHOWMSG("MangleName new_mi failed");
  2622.         }
  2623.  
  2624.         UnmangleName(&old,&old_mi);
  2625.     }
  2626.     else
  2627.     {
  2628.         SHOWMSG("MangleName old_mi failed");
  2629.     }
  2630.  
  2631.     RETURN(result);
  2632.     return(result);
  2633. }
  2634.  
  2635. /******************************************************************************/
  2636.  
  2637. char *
  2638. amiga_getcwd(char *buf, size_t size)
  2639. {
  2640.     char *result = NULL;
  2641.  
  2642.     chkabort();
  2643.  
  2644.     ASSERT(buf != NULL);
  2645.  
  2646.     ENTER();
  2647.     SHOWVALUE(buf);
  2648.     SHOWVALUE(size);
  2649.  
  2650.     if(CurrentDirName[0] == '/')
  2651.     {
  2652.         strncpy(buf,CurrentDirName,size-1);
  2653.         buf[size-1] = '\0';
  2654.         result = buf;
  2655.     }
  2656.     else
  2657.     {
  2658.         BPTR oldDir;
  2659.  
  2660.         ForbidDOS();
  2661.  
  2662.         oldDir = CurrentDir(ZERO);
  2663.  
  2664.         if(NameFromLock(oldDir,buf,size))
  2665.         {
  2666.             if(MapFileNameAmigaToUnix(buf,buf,size) == OK)
  2667.                 result = buf;
  2668.         }
  2669.         else
  2670.         {
  2671.             MapIoErrToErrno();
  2672.         }
  2673.  
  2674.         CurrentDir(oldDir);
  2675.  
  2676.         PermitDOS();
  2677.     }
  2678.  
  2679.     SHOWSTRING(result);
  2680.  
  2681.     RETURN(result);
  2682.     return(result);
  2683. }
  2684.  
  2685. /******************************************************************************/
  2686.  
  2687. #define SET_FILESIZE_ERROR (-1)
  2688.  
  2689. int
  2690. amiga_ftruncate(int fd,off_t size)
  2691. {
  2692.     struct UFB * ufb;
  2693.     int result = ERROR;
  2694.  
  2695.     chkabort();
  2696.  
  2697.     ENTER();
  2698.     SHOWVALUE(fd);
  2699.     SHOWVALUE(size);
  2700.  
  2701.     ufb = chkufb(fd);
  2702.     if(ufb != NULL)
  2703.     {
  2704.         ForbidDOS();
  2705.  
  2706.         if(SetFileSize((BPTR)ufb->ufbfh,size,OFFSET_BEGINNING) != SET_FILESIZE_ERROR)
  2707.             result = OK;
  2708.         else
  2709.             MapIoErrToErrno();
  2710.  
  2711.         PermitDOS();
  2712.     }
  2713.     else
  2714.     {
  2715.         errno = EBADF;
  2716.     }
  2717.  
  2718.     RETURN(result);
  2719.     return(result);
  2720. }
  2721.  
  2722. /******************************************************************************/
  2723.  
  2724. int
  2725. amiga_accept(int sockfd,struct sockaddr *cliaddr,int *addrlen)
  2726. {
  2727.     struct UFB * ufb;
  2728.     int result = ERROR;
  2729.  
  2730.     chkabort();
  2731.  
  2732.     ASSERT(cliaddr != NULL && addrlen != NULL);
  2733.  
  2734.     ENTER();
  2735.     SHOWVALUE(sockfd);
  2736.     SHOWVALUE(cliaddr);
  2737.     SHOWVALUE(addrlen);
  2738.  
  2739.     ufb = chkufb(sockfd);
  2740.     if(ufb != NULL && FLAG_IS_SET(ufb->ufbflg,UFB_IS_SOCKET))
  2741.         result = accept(ufb->ufbfh,cliaddr,(LONG *)addrlen);
  2742.     else
  2743.         errno = ENOTSOCK;
  2744.  
  2745.     RETURN(result);
  2746.     return(result);
  2747. }
  2748.  
  2749. /******************************************************************************/
  2750.  
  2751. int
  2752. amiga_bind(int sockfd,struct sockaddr *name,int namelen)
  2753. {
  2754.     struct UFB * ufb;
  2755.     int result = ERROR;
  2756.  
  2757.     chkabort();
  2758.  
  2759.     ASSERT(name != NULL);
  2760.  
  2761.     ENTER();
  2762.     SHOWVALUE(sockfd);
  2763.     SHOWVALUE(name);
  2764.     SHOWVALUE(namelen);
  2765.  
  2766.     ufb = chkufb(sockfd);
  2767.     if(ufb != NULL && FLAG_IS_SET(ufb->ufbflg,UFB_IS_SOCKET))
  2768.         result = bind(ufb->ufbfh,name,namelen);
  2769.     else
  2770.         errno = ENOTSOCK;
  2771.  
  2772.     RETURN(result);
  2773.     return(result);
  2774. }
  2775.  
  2776. /******************************************************************************/
  2777.  
  2778. int
  2779. amiga_close(int fd)
  2780. {
  2781.     struct UFB * ufb;
  2782.     int result = ERROR;
  2783.  
  2784.     chkabort();
  2785.  
  2786.     ENTER();
  2787.     SHOWVALUE(fd);
  2788.  
  2789.     ufb = chkufb(fd);
  2790.     if(ufb != NULL && FLAG_IS_SET(ufb->ufbflg,UFB_IS_SOCKET))
  2791.     {
  2792.         result = CloseSocket(ufb->ufbfh);
  2793.         CLEAR_FLAG(ufb->ufbflg,UFB_IS_SOCKET);
  2794.  
  2795.         /* Make sure that the descriptor looks like a file again. */
  2796.         RestoreDescriptor(ufb);
  2797.  
  2798.         close(fd);
  2799.     }
  2800.     else
  2801.     {
  2802.         if(ufb != NULL)
  2803.         {
  2804.             /* Don't close the stdio streams! */
  2805.             if(fd == 0 || fd == 1 || fd == 2)
  2806.             {
  2807.                 D(("Attempt to muck with fd #%ld!",fd));
  2808.  
  2809.                 errno = EBADF;
  2810.             }
  2811.             else
  2812.             {
  2813.                 char fileName[MAX_FILENAME_LEN];
  2814.                 BOOL removeIt = FALSE;
  2815.  
  2816.                 if(FLAG_IS_SET(ufb->ufbflg,UFB_UNLINK))
  2817.                 {
  2818.                     removeIt = NameFromFH((BPTR)ufb->ufbfh,fileName,sizeof(fileName));
  2819.  
  2820.                     CLEAR_FLAG(ufb->ufbflg,UFB_UNLINK);
  2821.                 }
  2822.  
  2823.                 CleanupFileLocks(fd);
  2824.  
  2825.                 result = close(fd);
  2826.  
  2827.                 if(removeIt)
  2828.                     DeleteFile(fileName);
  2829.             }
  2830.         }
  2831.         else
  2832.         {
  2833.             errno = EBADF;
  2834.         }
  2835.     }
  2836.  
  2837.     RETURN(result);
  2838.     return(result);
  2839. }
  2840.  
  2841. /******************************************************************************/
  2842.  
  2843. int
  2844. amiga_connect(int sockfd,struct sockaddr *name,int namelen)
  2845. {
  2846.     struct UFB * ufb;
  2847.     int result = ERROR;
  2848.  
  2849.     chkabort();
  2850.  
  2851.     ASSERT(name != NULL && namelen > 0);
  2852.  
  2853.     ENTER();
  2854.     SHOWVALUE(sockfd);
  2855.     SHOWVALUE(name);
  2856.     SHOWVALUE(namelen);
  2857.  
  2858.     ufb = chkufb(sockfd);
  2859.     if(ufb != NULL && FLAG_IS_SET(ufb->ufbflg,UFB_IS_SOCKET))
  2860.         result = connect(ufb->ufbfh,name,namelen);
  2861.     else
  2862.         errno = ENOTSOCK;
  2863.  
  2864.     RETURN(result);
  2865.     return(result);
  2866. }
  2867.  
  2868. /******************************************************************************/
  2869.  
  2870. int
  2871. amiga_getpeername(int sockfd,struct sockaddr *name,int *namelen)
  2872. {
  2873.     struct UFB * ufb;
  2874.     int result = ERROR;
  2875.  
  2876.     chkabort();
  2877.  
  2878.     ASSERT(name != NULL && namelen != NULL);
  2879.  
  2880.     ENTER();
  2881.     SHOWVALUE(sockfd);
  2882.     SHOWVALUE(name);
  2883.     SHOWVALUE(namelen);
  2884.  
  2885.     ufb = chkufb(sockfd);
  2886.     if(ufb != NULL && FLAG_IS_SET(ufb->ufbflg,UFB_IS_SOCKET))
  2887.         result = getpeername(ufb->ufbfh,name,(LONG *)namelen);
  2888.     else
  2889.         errno = ENOTSOCK;
  2890.  
  2891.     RETURN(result);
  2892.     return(result);
  2893. }
  2894.  
  2895. /******************************************************************************/
  2896.  
  2897. int
  2898. amiga_getsockopt(int sockfd,int level,int optname,VOID *optval,int *optlen)
  2899. {
  2900.     struct UFB * ufb;
  2901.     int result = ERROR;
  2902.  
  2903.     chkabort();
  2904.  
  2905.     ASSERT(optval != NULL && optlen != NULL);
  2906.  
  2907.     ENTER();
  2908.     SHOWVALUE(sockfd);
  2909.     SHOWVALUE(level);
  2910.     SHOWVALUE(optname);
  2911.     SHOWVALUE(optval);
  2912.     SHOWVALUE(optlen);
  2913.  
  2914.     ufb = chkufb(sockfd);
  2915.     if(ufb != NULL && FLAG_IS_SET(ufb->ufbflg,UFB_IS_SOCKET))
  2916.         result = getsockopt(ufb->ufbfh,level,optname,optval,(LONG *)optlen);
  2917.     else
  2918.         errno = ENOTSOCK;
  2919.  
  2920.     RETURN(result);
  2921.     return(result);
  2922. }
  2923.  
  2924. /******************************************************************************/
  2925.  
  2926. int
  2927. amiga_ioctl(int fd,unsigned long request,char *arg)
  2928. {
  2929.     struct UFB * ufb;
  2930.     int result = ERROR;
  2931.  
  2932.     chkabort();
  2933.  
  2934.     ASSERT(arg != NULL);
  2935.  
  2936.     ENTER();
  2937.     SHOWVALUE(fd);
  2938.     SHOWVALUE(request);
  2939.     SHOWVALUE(arg);
  2940.  
  2941.     ufb = chkufb(fd);
  2942.     if(ufb != NULL && FLAG_IS_SET(ufb->ufbflg,UFB_IS_SOCKET))
  2943.         result = IoctlSocket(ufb->ufbfh,request,arg);
  2944.     else
  2945.         errno = ENOTSOCK;
  2946.  
  2947.     RETURN(result);
  2948.     return(result);
  2949. }
  2950.  
  2951. /******************************************************************************/
  2952.  
  2953. int
  2954. amiga_listen(int sockfd,int backlog)
  2955. {
  2956.     struct UFB * ufb;
  2957.     int result = ERROR;
  2958.  
  2959.     chkabort();
  2960.  
  2961.     ENTER();
  2962.     SHOWVALUE(sockfd);
  2963.     SHOWVALUE(backlog);
  2964.  
  2965.     ufb = chkufb(sockfd);
  2966.     if(ufb != NULL && FLAG_IS_SET(ufb->ufbflg,UFB_IS_SOCKET))
  2967.         result = listen(ufb->ufbfh,backlog);
  2968.     else
  2969.         errno = ENOTSOCK;
  2970.  
  2971.     RETURN(result);
  2972.     return(result);
  2973. }
  2974.  
  2975. /******************************************************************************/
  2976.  
  2977. int
  2978. amiga_read(int fd,VOID *data,unsigned int size)
  2979. {
  2980.     struct UFB * ufb;
  2981.     int result;
  2982.  
  2983.     chkabort();
  2984.  
  2985.     ASSERT(data != NULL);
  2986.  
  2987.     ENTER();
  2988.     SHOWVALUE(fd);
  2989.     SHOWVALUE(data);
  2990.     SHOWVALUE(size);
  2991.  
  2992.     ufb = chkufb(fd);
  2993.     if(ufb != NULL && FLAG_IS_SET(ufb->ufbflg,UFB_IS_SOCKET))
  2994.     {
  2995.         SHOWMSG("input from socket");
  2996.         result = recv(ufb->ufbfh,data,size,0);
  2997.     }
  2998.     else
  2999.     {
  3000.         SHOWMSG("input from file");
  3001.         ForbidDOS();
  3002.         result = read(fd,data,size);
  3003.         PermitDOS();
  3004.     }
  3005.  
  3006.     RETURN(result);
  3007.     return(result);
  3008. }
  3009.  
  3010. /******************************************************************************/
  3011.  
  3012. int
  3013. amiga_recvfrom(int sockfd,VOID *buff,int len,int flags,struct sockaddr *from,int *fromlen)
  3014. {
  3015.     struct UFB * ufb;
  3016.     int result = ERROR;
  3017.  
  3018.     chkabort();
  3019.  
  3020.     ASSERT(buff != NULL && from != NULL && fromlen != NULL);
  3021.  
  3022.     ENTER();
  3023.     SHOWVALUE(sockfd);
  3024.     SHOWVALUE(buff);
  3025.     SHOWVALUE(len);
  3026.     SHOWVALUE(flags);
  3027.     SHOWVALUE(from);
  3028.     SHOWVALUE(fromlen);
  3029.  
  3030.     ufb = chkufb(sockfd);
  3031.     if(ufb != NULL && FLAG_IS_SET(ufb->ufbflg,UFB_IS_SOCKET))
  3032.         result = recvfrom(ufb->ufbfh,buff,len,flags,from,(LONG *)fromlen);
  3033.     else
  3034.         errno = ENOTSOCK;
  3035.  
  3036.     RETURN(result);
  3037.     return(result);
  3038. }
  3039.  
  3040. /******************************************************************************/
  3041.  
  3042. STATIC VOID
  3043. MapDescriptorSets(
  3044.     const fd_set *    input_fds,
  3045.     int                num_input_fds,
  3046.     fd_set *        socket_fds,
  3047.     int *            max_socket_fd_ptr,
  3048.     fd_set *        file_fds,
  3049.     int *            max_file_fd_ptr)
  3050. {
  3051.     FD_ZERO(socket_fds);
  3052.     FD_ZERO(file_fds);
  3053.  
  3054.     /* This routine maps file descriptor sets
  3055.      * from one format to another. We map
  3056.      * socket descriptors and regular file
  3057.      * descriptor sets.
  3058.      */
  3059.     if(input_fds != NULL && num_input_fds > 0)
  3060.     {
  3061.         int max_socket_fd = (*max_socket_fd_ptr);
  3062.         int max_file_fd = (*max_file_fd_ptr);
  3063.         struct UFB * ufb;
  3064.         int i;
  3065.  
  3066.         for(i = 0 ; i < num_input_fds ; i++)
  3067.         {
  3068.             if(FD_ISSET(i,input_fds))
  3069.             {
  3070.                 D(("fd to wait on #%ld",i));
  3071.  
  3072.                 ufb = chkufb(i);
  3073.                 if(ufb != NULL)
  3074.                 {
  3075.                     /* Is this a socket descriptor? */
  3076.                     if(FLAG_IS_SET(ufb->ufbflg,UFB_IS_SOCKET))
  3077.                     {
  3078.                         D(("fd #%ld is a socket.\n",i));
  3079.  
  3080.                         FD_SET(ufb->ufbfh,socket_fds);
  3081.  
  3082.                         if(max_socket_fd < ufb->ufbfh)
  3083.                             max_socket_fd = ufb->ufbfh;
  3084.                     }
  3085.                     else
  3086.                     {
  3087.                         D(("fd #%ld is a file.\n",i));
  3088.  
  3089.                         /* We only watch files bound to
  3090.                          * console streams.
  3091.                          */
  3092.                         if(IsInteractive((BPTR)ufb->ufbfh))
  3093.                         {
  3094.                             FD_SET(i,file_fds);
  3095.  
  3096.                             if(max_file_fd < i)
  3097.                                 max_file_fd = i;
  3098.                         }
  3099.                     }
  3100.                 }
  3101.             }
  3102.         }
  3103.  
  3104.         (*max_socket_fd_ptr)    = max_socket_fd;
  3105.         (*max_file_fd_ptr)        = max_file_fd;
  3106.     }
  3107. }
  3108.  
  3109. STATIC VOID
  3110. RemapDescriptorSets(
  3111.     const fd_set *    socket_fds,
  3112.     int                max_socket_fd,
  3113.     const fd_set *    file_fds,
  3114.     int                max_file_fd,
  3115.     fd_set *        output_fds,
  3116.     int                num_output_fds)
  3117. {
  3118.     /* This routine reverses the mapping established
  3119.      * above. We map the file and socket descriptor
  3120.      * sets back into the original set.
  3121.      */
  3122.     if(output_fds != NULL)
  3123.     {
  3124.         int fd;
  3125.  
  3126.         FD_ZERO(output_fds);
  3127.  
  3128.         for(fd = 0 ; fd <= max_socket_fd ; fd++)
  3129.         {
  3130.             if(FD_ISSET(fd,socket_fds))
  3131.             {
  3132.                 struct UFB * ufb;
  3133.                 int output_fd;
  3134.  
  3135.                 for(output_fd = 0 ; output_fd < num_output_fds ; output_fd++)
  3136.                 {
  3137.                     ufb = chkufb(output_fd);
  3138.                     if(ufb != NULL && FLAG_IS_SET(ufb->ufbflg,UFB_IS_SOCKET) && ufb->ufbfh == fd)
  3139.                     {
  3140.                         D(("fd #%ld has data",output_fd));
  3141.                         FD_SET(output_fd,output_fds);
  3142.                         break;
  3143.                     }
  3144.                 }
  3145.             }
  3146.         }
  3147.  
  3148.         for(fd = 0 ; fd <= max_file_fd ; fd++)
  3149.         {
  3150.             if(FD_ISSET(fd,file_fds))
  3151.             {
  3152.                 D(("fd #%ld has data",fd));
  3153.                 FD_SET(fd,output_fds);
  3154.             }
  3155.         }
  3156.     }
  3157. }
  3158.  
  3159. int
  3160. amiga_select(int num_fds,fd_set *read_fds,fd_set *write_fds,fd_set *except_fds,struct timeval *timeout)
  3161. {
  3162.     fd_set socket_read_fds;
  3163.     fd_set socket_write_fds;
  3164.     fd_set socket_except_fds;
  3165.     int max_socket_fd;
  3166.     fd_set file_read_fds;
  3167.     fd_set file_write_fds;
  3168.     fd_set file_except_fds;
  3169.     struct UFB * ufb;
  3170.     int max_file_fd;
  3171.     int result = 0;
  3172.  
  3173.     chkabort();
  3174.  
  3175.     ENTER();
  3176.  
  3177.     if(num_fds > FD_SETSIZE)
  3178.     {
  3179.         D(("Warning: %ld descriptor sets to wait on requested; only %ld available.",num_fds,FD_SETSIZE));
  3180.         num_fds = FD_SETSIZE;
  3181.     }
  3182.  
  3183.     max_socket_fd = -1;
  3184.     max_file_fd = -1;
  3185.  
  3186.     MapDescriptorSets(read_fds,        num_fds,    &socket_read_fds,    &max_socket_fd,    &file_read_fds,        &max_file_fd);
  3187.     MapDescriptorSets(write_fds,    num_fds,    &socket_write_fds,    &max_socket_fd,    &file_write_fds,    &max_file_fd);
  3188.     MapDescriptorSets(except_fds,    num_fds,    &socket_except_fds,    &max_socket_fd,    &file_except_fds,    &max_file_fd);
  3189.  
  3190.     D(("number of socket fds to work on == %ld",max_socket_fd+1));
  3191.     D(("number of file   fds to work on == %ld",max_file_fd+1));
  3192.  
  3193.     /* Wait for socket input? */
  3194.     if(max_socket_fd != -1)
  3195.     {
  3196.         /* Wait for file input, too? */
  3197.         if(max_file_fd != -1 && (timeout == NULL || timeout->tv_secs > 0 || timeout->tv_micro > 0))
  3198.         {
  3199.             struct timeval stopWhen;
  3200.             struct timeval zero;
  3201.             BOOL gotSomething;
  3202.             ULONG breakMask;
  3203.             int i;
  3204.  
  3205.             /* We are going to poll all streams; for the timeout
  3206.              * feature to work, we absolutely must know when to
  3207.              * stop polling.
  3208.              *
  3209.              * Why aren't we using asynchronous DOS packets?
  3210.              * The answer is that once a packet is sent, you
  3211.              * cannot easily abort it. Polling is safer in
  3212.              * that respect. Yes, I know that ACTION_STACK
  3213.              * can be used to fake input to a console stream,
  3214.              * but I'd rather not rely upon it.
  3215.              */
  3216.             if(timeout != NULL)
  3217.             {
  3218.                 GetSysTime((APTR)&stopWhen);
  3219.                 AddTime((APTR)&stopWhen,(APTR)timeout);
  3220.             }
  3221.             else
  3222.             {
  3223.                 /* No timeout, poll until we are interrupted
  3224.                  * or get input from any of the files. It's
  3225.                  * not really necessary to initialize this
  3226.                  * timeval, but it keeps the compiler happy.
  3227.                  */
  3228.                 memset(&stopWhen,0,sizeof(stopWhen));
  3229.             }
  3230.  
  3231.             while(TRUE)
  3232.             {
  3233.                 /* Check for break signal. */
  3234.                 chkabort();
  3235.  
  3236.                 /* Delay for a tick to avoid busy-waiting. */
  3237.                 Delay(1);
  3238.  
  3239.                 /* This tells WaitSelect() to poll the sockets for input. */
  3240.                 zero.tv_secs    = 0;
  3241.                 zero.tv_micro    = 0;
  3242.  
  3243.                 /* Signals to stop on; we want to stop when a break signal arrives. */
  3244.                 if(AllowBreak)
  3245.                     breakMask = SIGBREAKF_CTRL_C;
  3246.                 else
  3247.                     breakMask = 0;
  3248.  
  3249.                 /* Check for socket input. */
  3250.                 result = WaitSelect(max_socket_fd+1,&socket_read_fds,&socket_write_fds,&socket_except_fds,&zero,&breakMask);
  3251.  
  3252.                 /* Stop if a break signal arrives. */
  3253.                 if((result < 0 && errno == EINTR) || FLAG_IS_SET(breakMask,SIGBREAKF_CTRL_C))
  3254.                     raise(SIGINT);
  3255.  
  3256.                 /* Stop if the return value from WaitSelect is negative. */
  3257.                 if(result < 0)
  3258.                     break;
  3259.  
  3260.                 /* Did we get any socket input? */
  3261.                 gotSomething = (BOOL)(result > 0);
  3262.                 if(NOT gotSomething)
  3263.                 {
  3264.                     /* Check all files for input. We also poll
  3265.                      * them for input, but each with a little
  3266.                      * delay of about 1/50 of a second. We stop
  3267.                      * as soon as we find one file that has
  3268.                      * input in it.
  3269.                      */
  3270.                     for(i = 0 ; i <= max_file_fd ; i++)
  3271.                     {
  3272.                         if(FD_ISSET(i,&file_read_fds) ||
  3273.                            FD_ISSET(i,&file_write_fds) ||
  3274.                            FD_ISSET(i,&file_except_fds))
  3275.                         {
  3276.                             ufb = chkufb(i);
  3277.                             if(ufb != NULL)
  3278.                             {
  3279.                                 if(WaitForChar((BPTR)ufb->ufbfh,1))
  3280.                                 {
  3281.                                     gotSomething = TRUE;
  3282.                                     break;
  3283.                                 }
  3284.                             }
  3285.                         }
  3286.                     }
  3287.                 }
  3288.  
  3289.                 /* Did we get any input at all? */
  3290.                 if(gotSomething)
  3291.                 {
  3292.                     BOOL gotInput;
  3293.  
  3294.                     /* Now retest all files and remember
  3295.                      * those that had input.
  3296.                      */
  3297.                     for(i = 0 ; i <= max_file_fd ; i++)
  3298.                     {
  3299.                         gotInput = FALSE;
  3300.  
  3301.                         if(FD_ISSET(i,&file_read_fds) ||
  3302.                            FD_ISSET(i,&file_write_fds) ||
  3303.                            FD_ISSET(i,&file_except_fds))
  3304.                         {
  3305.                             ufb = chkufb(i);
  3306.                             if(ufb != NULL)
  3307.                             {
  3308.                                 /* Does this one have input? */
  3309.                                 gotInput = WaitForChar((BPTR)ufb->ufbfh,1);
  3310.                             }
  3311.                         }
  3312.  
  3313.                         if(gotInput)
  3314.                         {
  3315.                             /* Mark one more descriptor as
  3316.                              * having input.
  3317.                              */
  3318.                             result++;
  3319.                         }
  3320.                         else
  3321.                         {
  3322.                             /* Mark this descriptor as
  3323.                              * not having any input.
  3324.                              */
  3325.                             FD_CLR(i,&file_read_fds);
  3326.                             FD_CLR(i,&file_write_fds);
  3327.                             FD_CLR(i,&file_except_fds);
  3328.                         }
  3329.                     }
  3330.                 }
  3331.  
  3332.                 /* Did we get any input? If so, stop polling. */
  3333.                 if(result > 0)
  3334.                     break;
  3335.  
  3336.                 /* If a timeout was set, check if we are already
  3337.                  * beyond the point of time when we should have
  3338.                  * stopped polling.
  3339.                  */
  3340.                 if(timeout != NULL)
  3341.                 {
  3342.                     struct timeval now;
  3343.  
  3344.                     GetSysTime((APTR)&now);
  3345.  
  3346.                     if((-CmpTime((APTR)&now,(APTR)&stopWhen)) >= 0)
  3347.                         break;
  3348.                 }
  3349.             }
  3350.         }
  3351.         else
  3352.         {
  3353.             ULONG breakMask;
  3354.  
  3355.             if(AllowBreak)
  3356.                 breakMask = SIGBREAKF_CTRL_C;
  3357.             else
  3358.                 breakMask = 0;
  3359.  
  3360.             result = WaitSelect(max_socket_fd+1,&socket_read_fds,&socket_write_fds,&socket_except_fds,timeout,&breakMask);
  3361.             if((result < 0 && errno == EINTR) || FLAG_IS_SET(breakMask,SIGBREAKF_CTRL_C))
  3362.                 raise(SIGINT);
  3363.         }
  3364.     }
  3365.     else
  3366.     {
  3367.         /* Wait for file input? */
  3368.         if(max_file_fd != -1 && (timeout == NULL || timeout->tv_secs > 0 || timeout->tv_micro > 0))
  3369.         {
  3370.             struct timeval stopWhen;
  3371.             BOOL gotSomething;
  3372.             int i;
  3373.  
  3374.             if(timeout != NULL)
  3375.             {
  3376.                 GetSysTime((APTR)&stopWhen);
  3377.                 AddTime((APTR)&stopWhen,(APTR)timeout);
  3378.             }
  3379.             else
  3380.             {
  3381.                 memset(&stopWhen,0,sizeof(stopWhen));
  3382.             }
  3383.  
  3384.             while(TRUE)
  3385.             {
  3386.                 chkabort();
  3387.  
  3388.                 Delay(1);
  3389.  
  3390.                 gotSomething = FALSE;
  3391.                 for(i = 0 ; i <= max_file_fd ; i++)
  3392.                 {
  3393.                     if(FD_ISSET(i,&file_read_fds) ||
  3394.                        FD_ISSET(i,&file_write_fds) ||
  3395.                        FD_ISSET(i,&file_except_fds))
  3396.                     {
  3397.                         ufb = chkufb(i);
  3398.                         if(ufb != NULL)
  3399.                         {
  3400.                             if(WaitForChar((BPTR)ufb->ufbfh,1))
  3401.                             {
  3402.                                 gotSomething = TRUE;
  3403.                                 break;
  3404.                             }
  3405.                         }
  3406.                     }
  3407.                 }
  3408.  
  3409.                 if(gotSomething)
  3410.                 {
  3411.                     BOOL gotInput;
  3412.  
  3413.                     for(i = 0 ; i <= max_file_fd ; i++)
  3414.                     {
  3415.                         gotInput = FALSE;
  3416.  
  3417.                         if(FD_ISSET(i,&file_read_fds) ||
  3418.                            FD_ISSET(i,&file_write_fds) ||
  3419.                            FD_ISSET(i,&file_except_fds))
  3420.                         {
  3421.                             ufb = chkufb(i);
  3422.                             if(ufb != NULL)
  3423.                             {
  3424.                                 /* Does this one have input? */
  3425.                                 gotInput = WaitForChar((BPTR)ufb->ufbfh,1);
  3426.                             }
  3427.                         }
  3428.  
  3429.                         if(gotInput)
  3430.                         {
  3431.                             result++;
  3432.                         }
  3433.                         else
  3434.                         {
  3435.                             FD_CLR(i,&file_read_fds);
  3436.                             FD_CLR(i,&file_write_fds);
  3437.                             FD_CLR(i,&file_except_fds);
  3438.                         }
  3439.                     }
  3440.                 }
  3441.  
  3442.                 if(result > 0)
  3443.                     break;
  3444.  
  3445.                 if(timeout != NULL)
  3446.                 {
  3447.                     struct timeval now;
  3448.  
  3449.                     GetSysTime((APTR)&now);
  3450.  
  3451.                     if((-CmpTime((APTR)&now,(APTR)&stopWhen)) >= 0)
  3452.                         break;
  3453.                 }
  3454.             }
  3455.         }
  3456.     }
  3457.  
  3458.     /* The descriptor sets remain unchanged in
  3459.      * case of error.
  3460.      */
  3461.     if(result >= 0)
  3462.     {
  3463.         RemapDescriptorSets(&socket_read_fds,    max_socket_fd,    &file_read_fds,        max_file_fd,    read_fds,    num_fds);
  3464.         RemapDescriptorSets(&socket_write_fds,    max_socket_fd,    &file_write_fds,    max_file_fd,    write_fds,    num_fds);
  3465.         RemapDescriptorSets(&socket_except_fds,    max_socket_fd,    &file_except_fds,    max_file_fd,    except_fds,    num_fds);
  3466.     }
  3467.  
  3468.     RETURN(result);
  3469.     return(result);
  3470. }
  3471.  
  3472. /******************************************************************************/
  3473.  
  3474. int
  3475. amiga_sendto(int sockfd,VOID *buff,int len,int flags,struct sockaddr *to,int tolen)
  3476. {
  3477.     struct UFB * ufb;
  3478.     int result = ERROR;
  3479.  
  3480.     chkabort();
  3481.  
  3482.     ASSERT(buff != NULL && to != NULL);
  3483.  
  3484.     ENTER();
  3485.     SHOWVALUE(sockfd);
  3486.     SHOWVALUE(buff);
  3487.     SHOWVALUE(len);
  3488.     SHOWVALUE(flags);
  3489.     SHOWVALUE(to);
  3490.     SHOWVALUE(tolen);
  3491.  
  3492.     ufb = chkufb(sockfd);
  3493.     if(ufb != NULL && FLAG_IS_SET(ufb->ufbflg,UFB_IS_SOCKET))
  3494.         result = sendto(ufb->ufbfh,buff,len,flags,to,tolen);
  3495.     else
  3496.         errno = ENOTSOCK;
  3497.  
  3498.     RETURN(result);
  3499.     return(result);
  3500. }
  3501.  
  3502. /******************************************************************************/
  3503.  
  3504. int
  3505. amiga_setsockopt(int sockfd,int level,int optname,VOID *optval,int optlen)
  3506. {
  3507.     struct UFB * ufb;
  3508.     int result = ERROR;
  3509.  
  3510.     chkabort();
  3511.  
  3512.     ASSERT(optval != NULL);
  3513.  
  3514.     ENTER();
  3515.     SHOWVALUE(sockfd);
  3516.     SHOWVALUE(level);
  3517.     SHOWVALUE(optname);
  3518.     SHOWVALUE(optval);
  3519.     SHOWVALUE(optlen);
  3520.  
  3521.     ufb = chkufb(sockfd);
  3522.     if(ufb != NULL && FLAG_IS_SET(ufb->ufbflg,UFB_IS_SOCKET))
  3523.         result = setsockopt(ufb->ufbfh,level,optname,optval,optlen);
  3524.     else
  3525.         errno = ENOTSOCK;
  3526.  
  3527.     RETURN(result);
  3528.     return(result);
  3529. }
  3530.  
  3531. /******************************************************************************/
  3532.  
  3533. int
  3534. amiga_socket(int domain,int type,int protocol)
  3535. {
  3536.     int result = ERROR;
  3537.     int fd;
  3538.  
  3539.     chkabort();
  3540.  
  3541.     ENTER();
  3542.     SHOWVALUE(domain);
  3543.     SHOWVALUE(type);
  3544.     SHOWVALUE(protocol);
  3545.  
  3546.     /* We open a regular file that is guaranteed to
  3547.      * open in any case and then attach a socket
  3548.      * in place of the original file handle.
  3549.      */
  3550.     fd = open("NIL:",O_RDWR,0777);
  3551.     if(fd != -1)
  3552.     {
  3553.         struct UFB * ufb;
  3554.  
  3555.         ufb = chkufb(fd);
  3556.         if(ufb != NULL)
  3557.         {
  3558.             /* Save the original file handle value. */
  3559.             if(SaveDescriptor(ufb))
  3560.             {
  3561.                 int sockfd;
  3562.  
  3563.                 /* Now create the real socket. */
  3564.                 sockfd = socket(domain,type,protocol);
  3565.                 if(sockfd != -1)
  3566.                 {
  3567.                     /* Put the socket in place of the file handle. */
  3568.                     SET_FLAG(ufb->ufbflg,UFB_IS_SOCKET);
  3569.                     ufb->ufbfh = sockfd;
  3570.  
  3571.                     result = fd;
  3572.                 }
  3573.                 else
  3574.                 {
  3575.                     close(fd);
  3576.                 }
  3577.             }
  3578.             else
  3579.             {
  3580.                 close(fd);
  3581.                 errno = ENOMEM;
  3582.             }
  3583.         }
  3584.         else
  3585.         {
  3586.             close(fd);
  3587.             errno = EBADF;
  3588.         }
  3589.     }
  3590.  
  3591.     RETURN(result);
  3592.     return(result);
  3593. }
  3594.  
  3595. /******************************************************************************/
  3596.  
  3597. int
  3598. amiga_write(int fd,VOID *data,unsigned int size)
  3599. {
  3600.     struct UFB * ufb;
  3601.     int result;
  3602.  
  3603.     chkabort();
  3604.  
  3605.     ASSERT(data != NULL);
  3606.  
  3607.     ENTER();
  3608.     SHOWVALUE(fd);
  3609.     SHOWVALUE(data);
  3610.     SHOWVALUE(size);
  3611.  
  3612.     ufb = chkufb(fd);
  3613.     if(ufb != NULL && FLAG_IS_SET(ufb->ufbflg,UFB_IS_SOCKET))
  3614.     {
  3615.         result = send(ufb->ufbfh,data,size,0);
  3616.     }
  3617.     else
  3618.     {
  3619.         ForbidDOS();
  3620.         result = write(fd,data,size);
  3621.         PermitDOS();
  3622.     }
  3623.  
  3624.     RETURN(result);
  3625.     return(result);
  3626. }
  3627.  
  3628. /******************************************************************************/
  3629.  
  3630. STATIC VOID
  3631. ConvertFileInfoToStat(
  3632.     struct MsgPort * port,
  3633.     struct FileInfoBlock * fib,
  3634.     struct stat * st)
  3635. {
  3636.     ULONG flags;
  3637.     int mode;
  3638.     long time;
  3639.  
  3640.     /* This routine converts the contents of a FileInfoBlock
  3641.      * into information to fill a Unix-like stat data structure
  3642.      * with.
  3643.      */
  3644.     flags = fib->fib_Protection ^ (FIBF_READ|FIBF_WRITE|FIBF_EXECUTE|FIBF_DELETE);
  3645.  
  3646.     if(FIB_IS_DRAWER(fib))
  3647.         mode = S_IFDIR;
  3648.     else
  3649.         mode = S_IFREG;
  3650.  
  3651.     if(FLAG_IS_SET(flags,FIBF_READ))
  3652.         SET_FLAG(mode,S_IRUSR);
  3653.  
  3654.     if(FLAG_IS_SET(flags,FIBF_WRITE) && FLAG_IS_SET(flags,FIBF_DELETE))
  3655.         SET_FLAG(mode,S_IWUSR);
  3656.  
  3657.     if(FLAG_IS_SET(flags,FIBF_EXECUTE))
  3658.         SET_FLAG(mode,S_IXUSR);
  3659.  
  3660.  
  3661.     if(FLAG_IS_SET(flags,FIBF_GRP_READ))
  3662.         SET_FLAG(mode,S_IRGRP);
  3663.  
  3664.     if(FLAG_IS_SET(flags,FIBF_GRP_WRITE) && FLAG_IS_SET(flags,FIBF_GRP_DELETE))
  3665.         SET_FLAG(mode,S_IWGRP);
  3666.  
  3667.     if(FLAG_IS_SET(flags,FIBF_GRP_EXECUTE))
  3668.         SET_FLAG(mode,S_IXGRP);
  3669.  
  3670.  
  3671.     if(FLAG_IS_SET(flags,FIBF_OTR_READ))
  3672.         SET_FLAG(mode,S_IROTH);
  3673.  
  3674.     if(FLAG_IS_SET(flags,FIBF_OTR_WRITE) && FLAG_IS_SET(flags,FIBF_OTR_DELETE))
  3675.         SET_FLAG(mode,S_IWOTH);
  3676.  
  3677.     if(FLAG_IS_SET(flags,FIBF_OTR_EXECUTE))
  3678.         SET_FLAG(mode,S_IXOTH);
  3679.  
  3680.     time = fib->fib_Date.ds_Days * 24*60*60 +
  3681.            fib->fib_Date.ds_Minute * 60 +
  3682.           (fib->fib_Date.ds_Tick / TICKS_PER_SECOND);
  3683.  
  3684.     memset(st,0,sizeof(*st));
  3685.  
  3686.     st->st_dev        = (u_long)port;
  3687.     st->st_ino        = fib->fib_DiskKey;
  3688.     st->st_mode        = mode;
  3689.     st->st_mtime    = UNIX_TIME_OFFSET + time + 60*MinutesWest;    /* translate from local time to UTC */
  3690.     st->st_atime    = st->st_mtime;
  3691.     st->st_ctime    = st->st_mtime;
  3692.     st->st_uid        = fib->fib_OwnerUID;
  3693.     st->st_gid        = fib->fib_OwnerGID;
  3694.  
  3695.     if(FIB_IS_FILE(fib))
  3696.     {
  3697.         st->st_nlink = 1;
  3698.         st->st_size  = fib->fib_Size;
  3699.     }
  3700.     else
  3701.     {
  3702.         st->st_nlink = 2;
  3703.     }
  3704. }
  3705.  
  3706. int
  3707. amiga_stat(char *name, struct stat *st)
  3708. {
  3709.     char localName[MAX_FILENAME_LEN];
  3710.     struct MangleInfo mi;
  3711.     int result = ERROR;
  3712.  
  3713.     chkabort();
  3714.  
  3715.     ASSERT(name != NULL && st != NULL);
  3716.  
  3717.     ENTER();
  3718.     SHOWSTRING(name);
  3719.     SHOWVALUE(st);
  3720.  
  3721.     if(TranslateRelativePath(&name,localName,sizeof(localName)) == OK)
  3722.     {
  3723.         char * originalName = name;
  3724.  
  3725.         if(MangleName(&name,&mi) == OK)
  3726.         {
  3727.             int len;
  3728.  
  3729.             SHOWSTRING(name);
  3730.             SHOWSTRING(originalName);
  3731.  
  3732.             len = strlen(name);
  3733.             if((strcmp(originalName,"/") == SAME) || (len > 1 && name[len-2] == ':' && name[len-1] == '/'))
  3734.             {
  3735.                 struct timeval now;
  3736.  
  3737.                 SHOWMSG("this is the virtual root directory");
  3738.  
  3739.                 /* This must be our virtual root directory.
  3740.                  * Make something up.
  3741.                  */
  3742.                 memset(st,0,sizeof(*st));
  3743.                 GetSysTime((APTR)&now);
  3744.  
  3745.                 /* Nobody may write to this "directory". */
  3746.                 st->st_dev        = (u_long)"Virtual Root Directory";
  3747.                 st->st_ino        = 1;
  3748.                 st->st_mode        = S_IFDIR|S_IRUSR|S_IXUSR|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH;
  3749.                 st->st_nlink    = 2;
  3750.                 st->st_mtime    = UNIX_TIME_OFFSET + now.tv_secs + 60*MinutesWest;    /* translate from local time to UTC */
  3751.                 st->st_atime    = st->st_mtime;
  3752.                 st->st_ctime    = st->st_mtime;
  3753.  
  3754.                 result = OK;
  3755.             }
  3756.             else
  3757.             {
  3758.                 BPTR fileLock;
  3759.  
  3760.                 SHOWMSG("this is a drawer or a file");
  3761.  
  3762.                 ForbidDOS();
  3763.  
  3764.                 fileLock = Lock((STRPTR)name,SHARED_LOCK);
  3765.                 if(fileLock != ZERO)
  3766.                 {
  3767.                     struct FileInfoBlock __aligned fib;
  3768.  
  3769.                     if(Examine(fileLock,&fib))
  3770.                     {
  3771.                         BPTR parentDir;
  3772.  
  3773.                         /* Check if this is the root directory. */
  3774.                         parentDir = ParentDir(fileLock);
  3775.                         if(parentDir != ZERO)
  3776.                         {
  3777.                             /* This is not the root directory. */
  3778.                             UnLock(parentDir);
  3779.                         }
  3780.                         else
  3781.                         {
  3782.                             /* So this is the root directory. Make sure
  3783.                              * that we return proper protection bits for
  3784.                              * it, i.e. that the directory is always
  3785.                              * readable, writable, etc. This may be
  3786.                              * necessary since on the Amiga, root
  3787.                              * directories cannot have any protection
  3788.                              * bits set. Note that the "deletable"
  3789.                              * bits don't make much sense, but then
  3790.                              * these bits work together with the
  3791.                              * writable bits. The lowest four bits
  3792.                              * remain zero, which enables them all.
  3793.                              */
  3794.                             fib.fib_Protection = FIBF_OTR_READ |
  3795.                                                  FIBF_OTR_WRITE |
  3796.                                                  FIBF_OTR_EXECUTE |
  3797.                                                  FIBF_OTR_DELETE |
  3798.                                                  FIBF_GRP_READ |
  3799.                                                  FIBF_GRP_WRITE |
  3800.                                                  FIBF_GRP_EXECUTE |
  3801.                                                  FIBF_GRP_DELETE;
  3802.                         }
  3803.  
  3804.                         ConvertFileInfoToStat(((struct FileLock *)BADDR(fileLock))->fl_Task,&fib,st);
  3805.  
  3806.                         result = OK;
  3807.                     }
  3808.                     else
  3809.                     {
  3810.                         MapIoErrToErrno();
  3811.                     }
  3812.  
  3813.                     UnLock(fileLock);
  3814.                 }
  3815.                 else
  3816.                 {
  3817.                     LONG error = IoErr();
  3818.  
  3819.                     if(error == ERROR_OBJECT_IN_USE)
  3820.                     {
  3821.                         char parentName[MAX_FILENAME_LEN];
  3822.                         BPTR parentLock;
  3823.  
  3824.                         strcpy(parentName,name);
  3825.                         (*PathPart(parentName) = '\0');
  3826.  
  3827.                         parentLock = Lock(parentName,SHARED_LOCK);
  3828.                         if(parentLock != ZERO)
  3829.                         {
  3830.                             struct FileInfoBlock __aligned fib;
  3831.  
  3832.                             if(Examine(parentLock,&fib))
  3833.                             {
  3834.                                 STRPTR onlyFileName = FilePart(name);
  3835.  
  3836.                                 while(ExNext(parentLock,&fib))
  3837.                                 {
  3838.                                     if(Stricmp(fib.fib_FileName,onlyFileName) == SAME)
  3839.                                     {
  3840.                                         ConvertFileInfoToStat(((struct FileLock *)BADDR(parentLock))->fl_Task,&fib,st);
  3841.  
  3842.                                         result = OK;
  3843.                                         error = OK;
  3844.                                         break;
  3845.                                     }
  3846.                                 }
  3847.                             }
  3848.  
  3849.                             UnLock(parentLock);
  3850.                         }
  3851.                     }
  3852.  
  3853.                     if(error != OK)
  3854.                     {
  3855.                         SetIoErr(error);
  3856.  
  3857.                         MapIoErrToErrno();
  3858.                     }
  3859.                 }
  3860.  
  3861.                 PermitDOS();
  3862.             }
  3863.  
  3864.             if(result == OK)
  3865.             {
  3866.                 SHOWVALUE(st->st_dev);
  3867.                 SHOWVALUE(st->st_ino);
  3868.                 SHOWVALUE(st->st_size);
  3869.                 SHOWVALUE(st->st_nlink);
  3870.                 SHOWVALUE(st->st_mode);
  3871.                 SHOWVALUE(st->st_mtime);
  3872.                 SHOWVALUE(st->st_atime);
  3873.                 SHOWVALUE(st->st_ctime);
  3874.                 SHOWVALUE(st->st_uid);
  3875.                 SHOWVALUE(st->st_gid);
  3876.             }
  3877.             else
  3878.             {
  3879.                 SHOWVALUE(errno);
  3880.             }
  3881.  
  3882.             UnmangleName(&name,&mi);
  3883.         }
  3884.     }
  3885.  
  3886.     RETURN(result);
  3887.     return(result);
  3888. }
  3889.  
  3890. int
  3891. amiga_lstat(char *name, struct stat *statstruct)
  3892. {
  3893.     int result;
  3894.  
  3895.     chkabort();
  3896.  
  3897.     ENTER();
  3898.     SHOWSTRING(name);
  3899.     SHOWVALUE(statstruct);
  3900.  
  3901.     result = amiga_stat(name,statstruct);
  3902.  
  3903.     RETURN(result);
  3904.     return(result);
  3905. }
  3906.  
  3907. int
  3908. amiga_fstat(int fd,struct stat * st)
  3909. {
  3910.     struct UFB * ufb;
  3911.     int result = ERROR;
  3912.  
  3913.     chkabort();
  3914.  
  3915.     ASSERT(st != NULL);
  3916.  
  3917.     ENTER();
  3918.     SHOWVALUE(fd);
  3919.     SHOWVALUE(st);
  3920.  
  3921.     ufb = chkufb(fd);
  3922.     if(ufb != NULL)
  3923.     {
  3924.         if(FLAG_IS_SET(ufb->ufbflg,UFB_IS_SOCKET))
  3925.         {
  3926.             long value;
  3927.             long size = sizeof(value);
  3928.  
  3929.             memset(st,0,sizeof(*st));
  3930.  
  3931.             st->st_dev    = (u_long)SocketBase;
  3932.             st->st_mode    = S_IFSOCK | S_IRUSR | S_IWUSR;
  3933.             st->st_uid    = geteuid();
  3934.             st->st_gid    = getegid();
  3935.  
  3936.             if(getsockopt(fd,SOL_SOCKET,SO_SNDBUF,&value,&size) == 0)
  3937.                 st->st_blksize = value;
  3938.  
  3939.             result = OK;
  3940.         }
  3941.         else
  3942.         {
  3943.             struct FileHandle * fileHandle = BADDR(ufb->ufbfh);
  3944.  
  3945.             /* Make sure that this stream doesn't
  3946.              * really refer to "NIL:".
  3947.              */
  3948.             if(fileHandle->fh_Type != NULL)
  3949.             {
  3950.                 struct FileInfoBlock __aligned fib;
  3951.  
  3952.                 ForbidDOS();
  3953.  
  3954.                 if(ExamineFH(ufb->ufbfh,&fib))
  3955.                 {
  3956.                     ConvertFileInfoToStat(fileHandle->fh_Type,&fib,st);
  3957.  
  3958.                     result = OK;
  3959.                 }
  3960.                 else
  3961.                 {
  3962.                     MapIoErrToErrno();
  3963.                 }
  3964.  
  3965.                 PermitDOS();
  3966.             }
  3967.             else
  3968.             {
  3969.                 struct timeval tv;
  3970.  
  3971.                 /* Make up some phony data for a NIL: file handle. */
  3972.                 memset(st,0,sizeof(*st));
  3973.  
  3974.                 GetSysTime((APTR)&tv);
  3975.  
  3976.                 st->st_dev        = (u_long)0;
  3977.                 st->st_mode        = S_IFREG | S_IRUSR | S_IWUSR;
  3978.                 st->st_mtime    = UNIX_TIME_OFFSET + tv.tv_secs + 60*MinutesWest;    /* translate from local time to UTC */
  3979.                 st->st_atime    = st->st_mtime;
  3980.                 st->st_ctime    = st->st_mtime;
  3981.  
  3982.                 result = OK;
  3983.             }
  3984.         }
  3985.     }
  3986.     else
  3987.     {
  3988.         errno = EBADF;
  3989.     }
  3990.  
  3991.     RETURN(result);
  3992.     return(result);
  3993. }
  3994.  
  3995. /******************************************************************************/
  3996.  
  3997. int
  3998. amiga_chmod(char *name,int mode)
  3999. {
  4000.     struct MangleInfo mi;
  4001.     ULONG flags = 0;
  4002.     int result = ERROR;
  4003.  
  4004.     chkabort();
  4005.  
  4006.     ASSERT(name != NULL);
  4007.  
  4008.     ENTER();
  4009.     SHOWSTRING(name);
  4010.     SHOWVALUE(mode);
  4011.  
  4012.     /* Convert the file access modes into
  4013.      * Amiga typical protection bits.
  4014.      */
  4015.     if(FLAG_IS_SET(mode,S_IRUSR))
  4016.         SET_FLAG(flags,FIBF_READ);
  4017.  
  4018.     if(FLAG_IS_SET(mode,S_IWUSR))
  4019.     {
  4020.         SET_FLAG(flags,FIBF_WRITE);
  4021.         SET_FLAG(flags,FIBF_DELETE);
  4022.     }
  4023.  
  4024.     if(FLAG_IS_SET(mode,S_IXUSR))
  4025.         SET_FLAG(flags,FIBF_EXECUTE);
  4026.  
  4027.  
  4028.     if(FLAG_IS_SET(mode,S_IRGRP))
  4029.         SET_FLAG(flags,FIBF_GRP_READ);
  4030.  
  4031.     if(FLAG_IS_SET(mode,S_IWGRP))
  4032.     {
  4033.         SET_FLAG(flags,FIBF_GRP_WRITE);
  4034.         SET_FLAG(flags,FIBF_GRP_DELETE);
  4035.     }
  4036.  
  4037.     if(FLAG_IS_SET(mode,S_IXGRP))
  4038.         SET_FLAG(flags,FIBF_GRP_EXECUTE);
  4039.  
  4040.  
  4041.     if(FLAG_IS_SET(mode,S_IROTH))
  4042.         SET_FLAG(flags,FIBF_OTR_READ);
  4043.  
  4044.     if(FLAG_IS_SET(mode,S_IWOTH))
  4045.     {
  4046.         SET_FLAG(flags,FIBF_OTR_WRITE);
  4047.         SET_FLAG(flags,FIBF_OTR_DELETE);
  4048.     }
  4049.  
  4050.     if(FLAG_IS_SET(mode,S_IXOTH))
  4051.         SET_FLAG(flags,FIBF_OTR_EXECUTE);
  4052.  
  4053.     flags ^= (FIBF_READ|FIBF_WRITE|FIBF_EXECUTE|FIBF_DELETE);
  4054.  
  4055.     if(MangleName(&name,&mi) == OK)
  4056.     {
  4057.         ForbidDOS();
  4058.  
  4059.         if(SetProtection(name,flags))
  4060.         {
  4061.             result = OK;
  4062.         }
  4063.         else
  4064.         {
  4065.             LONG error = IoErr();
  4066.  
  4067.             /* Note sure about this one; is it really that important
  4068.              * that the file attribute change succeeds? This is a definite
  4069.              * FIXME.
  4070.              */
  4071.             if(error == ERROR_OBJECT_IN_USE)
  4072.             {
  4073.                 result = OK;
  4074.             }
  4075.             else
  4076.             {
  4077.                 SetIoErr(error);
  4078.  
  4079.                 MapIoErrToErrno();
  4080.             }
  4081.         }
  4082.  
  4083.         PermitDOS();
  4084.  
  4085.         UnmangleName(&name,&mi);
  4086.     }
  4087.  
  4088.     RETURN(result);
  4089.     return(result);
  4090. }
  4091.  
  4092. /******************************************************************************/
  4093.  
  4094. int
  4095. amiga_dup(int fd)
  4096. {
  4097.     struct UFB * ufb;
  4098.     int result = ERROR;
  4099.  
  4100.     chkabort();
  4101.  
  4102.     ENTER();
  4103.     SHOWVALUE(fd);
  4104.  
  4105.     ufb = chkufb(fd);
  4106.     if(ufb != NULL && FLAG_IS_SET(ufb->ufbflg,UFB_IS_SOCKET))
  4107.     {
  4108.         fd = open("NIL:",O_RDWR,0777);
  4109.         if(fd != -1)
  4110.         {
  4111.             struct UFB * ufb2;
  4112.  
  4113.             ufb2 = chkufb(fd);
  4114.             if(ufb2 != NULL)
  4115.             {
  4116.                 if(SaveDescriptor(ufb2))
  4117.                 {
  4118.                     int sockfd;
  4119.  
  4120.                     sockfd = Dup2Socket(ufb->ufbfh,-1);
  4121.                     if(sockfd != -1)
  4122.                     {
  4123.                         SET_FLAG(ufb2->ufbflg,UFB_IS_SOCKET);
  4124.                         ufb2->ufbfh = sockfd;
  4125.  
  4126.                         result = fd;
  4127.                     }
  4128.                     else
  4129.                     {
  4130.                         close(fd);
  4131.                     }
  4132.                 }
  4133.                 else
  4134.                 {
  4135.                     close(fd);
  4136.                     errno = ENOMEM;
  4137.                 }
  4138.             }
  4139.             else
  4140.             {
  4141.                 close(fd);
  4142.                 errno = EBADF;
  4143.             }
  4144.         }
  4145.     }
  4146.     else
  4147.     {
  4148.         errno = ENOTSOCK;
  4149.     }
  4150.  
  4151.     RETURN(result);
  4152.     return(result);
  4153. }
  4154.  
  4155. /******************************************************************************/
  4156.  
  4157. int
  4158. amiga_dup2(int old_fd,int new_fd)
  4159. {
  4160.     struct UFB * old_ufb;
  4161.     struct UFB * new_ufb;
  4162.     int result = ERROR;
  4163.  
  4164.     chkabort();
  4165.  
  4166.     ENTER();
  4167.     SHOWVALUE(old_fd);
  4168.     SHOWVALUE(new_fd);
  4169.  
  4170.     old_ufb = chkufb(old_fd);
  4171.     new_ufb = chkufb(new_fd);
  4172.  
  4173.     if(old_ufb != NULL && FLAG_IS_SET(old_ufb->ufbflg,UFB_IS_SOCKET) && new_ufb != NULL)
  4174.     {
  4175.         int sockfd;
  4176.  
  4177.         if(FLAG_IS_SET(new_ufb->ufbflg,UFB_IS_SOCKET))
  4178.         {
  4179.             CloseSocket(new_ufb->ufbfh);
  4180.             sockfd = Dup2Socket(old_ufb->ufbfh,new_ufb->ufbfh);
  4181.         }
  4182.         else
  4183.         {
  4184.             if(SaveDescriptor(new_ufb))
  4185.             {
  4186.                 sockfd = Dup2Socket(old_ufb->ufbfh,-1);
  4187.             }
  4188.             else
  4189.             {
  4190.                 sockfd = -1;
  4191.                 errno = ENOMEM;
  4192.             }
  4193.         }
  4194.  
  4195.         if(sockfd != -1)
  4196.         {
  4197.             SET_FLAG(new_ufb->ufbflg,UFB_IS_SOCKET);
  4198.             new_ufb->ufbfh = sockfd;
  4199.  
  4200.             result = new_fd;
  4201.         }
  4202.     }
  4203.     else
  4204.     {
  4205.         errno = ENOTSOCK;
  4206.     }
  4207.  
  4208.     RETURN(result);
  4209.     return(result);
  4210. }
  4211.  
  4212. /******************************************************************************/
  4213.  
  4214. int
  4215. amiga_chown(char *name,uid_t uid,gid_t gid)
  4216. {
  4217.     struct MangleInfo mi;
  4218.     int result = ERROR;
  4219.  
  4220.     chkabort();
  4221.  
  4222.     ASSERT(name != NULL);
  4223.  
  4224.     ENTER();
  4225.     SHOWSTRING(name);
  4226.     SHOWVALUE(uid);
  4227.     SHOWVALUE(gid);
  4228.  
  4229.     if(MangleName(&name,&mi) == OK)
  4230.     {
  4231.         /* AmigaDOS 3.0 and up have a SetOwner() call. */
  4232.         if(DOSBase->lib_Version >= 39)
  4233.         {
  4234.             if(SetOwner(name,(((LONG)uid) << 16) | gid))
  4235.                 result = OK;
  4236.             else
  4237.                 MapIoErrToErrno();
  4238.         }
  4239.         else
  4240.         {
  4241.             struct DevProc * dvp;
  4242.  
  4243.             /* For 2.04 and 2.1 we'll have to do this
  4244.              * manually...
  4245.              */
  4246.             dvp = GetDeviceProc(name,NULL);
  4247.             if(dvp != NULL)
  4248.             {
  4249.                 char __aligned newName[MAX_BSTR_LEN];
  4250.  
  4251.                 newName[0] = strlen(name);
  4252.                 strncpy(&newName[1],name,newName[0]);
  4253.  
  4254.                 /* This is almost identical in operation to ACTION_SET_PROTECTION. */
  4255.                 if(DoPkt(dvp->dvp_Port,ACTION_SET_OWNER,dvp->dvp_Lock,MKBADDR(newName),(((LONG)uid) << 16) | gid,0,0))
  4256.                     result = OK;
  4257.                 else
  4258.                     MapIoErrToErrno();
  4259.  
  4260.                 FreeDeviceProc(dvp);
  4261.             }
  4262.             else
  4263.             {
  4264.                 MapIoErrToErrno();
  4265.             }
  4266.         }
  4267.  
  4268.         UnmangleName(&name,&mi);
  4269.     }
  4270.  
  4271.     RETURN(result);
  4272.     return(result);
  4273. }
  4274.  
  4275. /******************************************************************************/
  4276.  
  4277. int
  4278. amiga_setegid(gid_t g)
  4279. {
  4280.     int result;
  4281.  
  4282.     chkabort();
  4283.  
  4284.     ENTER();
  4285.     SHOWVALUE(g);
  4286.  
  4287.     result = setregid(-1,g);
  4288.  
  4289.     RETURN(result);
  4290.     return(result);
  4291. }
  4292.  
  4293. /******************************************************************************/
  4294.  
  4295. int
  4296. amiga_seteuid(uid_t u)
  4297. {
  4298.     int result;
  4299.  
  4300.     chkabort();
  4301.  
  4302.     ENTER();
  4303.     SHOWVALUE(u);
  4304.     result = setreuid(-1,u);
  4305.  
  4306.     RETURN(result);
  4307.     return(result);
  4308. }
  4309.  
  4310. /******************************************************************************/
  4311.  
  4312. int
  4313. amiga_gettimeofday(struct timeval *tv)
  4314. {
  4315.     chkabort();
  4316.  
  4317.     ENTER();
  4318.     SHOWVALUE(tv);
  4319.  
  4320.     if(tv != NULL)
  4321.     {
  4322.         GetSysTime((APTR)tv);
  4323.         tv->tv_secs += UNIX_TIME_OFFSET + 60*MinutesWest;    /* translate from local time to UTC */
  4324.  
  4325.         SHOWVALUE(tv->tv_secs);
  4326.         SHOWVALUE(tv->tv_micro);
  4327.     }
  4328.  
  4329.     RETURN(0);
  4330.     return(0);
  4331. }
  4332.  
  4333. /******************************************************************************/
  4334.  
  4335. int
  4336. amiga_utime(char *name,struct utimbuf *time)
  4337. {
  4338.     struct MangleInfo mi;
  4339.     struct DateStamp ds;
  4340.     int result = ERROR;
  4341.  
  4342.     chkabort();
  4343.  
  4344.     ASSERT(name != NULL);
  4345.  
  4346.     ENTER();
  4347.     SHOWSTRING(name);
  4348.     SHOWVALUE(time);
  4349.  
  4350.     /* Use the current time? */
  4351.     if(time == NULL)
  4352.     {
  4353.         DateStamp(&ds);
  4354.     }
  4355.     else
  4356.     {
  4357.         ULONG seconds;
  4358.  
  4359.         /* Convert the time given. */
  4360.         if(time->modtime < (UNIX_TIME_OFFSET + 60*MinutesWest))
  4361.             seconds = 0;
  4362.         else
  4363.             seconds = time->modtime - (UNIX_TIME_OFFSET + 60*MinutesWest);    /* translate from UTC to local time */
  4364.  
  4365.         ds.ds_Days        = (seconds / (24*60*60));
  4366.         ds.ds_Minute    = (seconds % (24*60*60)) / 60;
  4367.         ds.ds_Tick        = (seconds               % 60) * TICKS_PER_SECOND;
  4368.     }
  4369.  
  4370.     if(MangleName(&name,&mi) == OK)
  4371.     {
  4372.         ForbidDOS();
  4373.  
  4374.         if(SetFileDate((STRPTR)name,&ds))
  4375.         {
  4376.             result = OK;
  4377.         }
  4378.         else
  4379.         {
  4380.             LONG error = IoErr();
  4381.  
  4382.             /* Note sure about this one; is it really that important
  4383.              * that the file date change succeeds? This is a definite
  4384.              * FIXME.
  4385.              */
  4386.             if(error == ERROR_OBJECT_IN_USE)
  4387.             {
  4388.                 result = OK;
  4389.             }
  4390.             else
  4391.             {
  4392.                 SetIoErr(error);
  4393.  
  4394.                 MapIoErrToErrno();
  4395.             }
  4396.         }
  4397.  
  4398.         PermitDOS();
  4399.  
  4400.         UnmangleName(&name,&mi);
  4401.     }
  4402.  
  4403.     RETURN(result);
  4404.     return(result);
  4405. }
  4406.  
  4407. /******************************************************************************/
  4408.  
  4409. VOID
  4410. amiga_sleep(unsigned int seconds)
  4411. {
  4412.     chkabort();
  4413.  
  4414.     ENTER();
  4415.     SHOWVALUE(seconds);
  4416.  
  4417.     if(seconds > 0)
  4418.     {
  4419.         ULONG timerSignal = (1UL << TimerPort->mp_SigBit);
  4420.         ULONG signalsReceived;
  4421.         ULONG signalsToWaitFor;
  4422.  
  4423.         TimerRequest->tr_node.io_Command    = TR_ADDREQUEST;
  4424.         TimerRequest->tr_time.tv_secs        = seconds;
  4425.         TimerRequest->tr_time.tv_micro        = 0;
  4426.  
  4427.         SetSignal(0,timerSignal);
  4428.         SendIO((struct IORequest *)TimerRequest);
  4429.  
  4430.         signalsToWaitFor = timerSignal;
  4431.         if(AllowBreak)
  4432.             signalsToWaitFor |= SIGBREAKF_CTRL_C;
  4433.  
  4434.         signalsReceived = Wait(signalsToWaitFor);
  4435.  
  4436.         /* Did we get a break signal while we were sleeping? */
  4437.         if(FLAG_IS_SET(signalsReceived,SIGBREAKF_CTRL_C))
  4438.         {
  4439.             if(CheckIO((struct IORequest *)TimerRequest) == BUSY)
  4440.                 AbortIO((struct IORequest *)TimerRequest);
  4441.  
  4442.             WaitIO((struct IORequest *)TimerRequest);
  4443.  
  4444.             /* And pull the brakes... */
  4445.             raise(SIGINT);
  4446.         }
  4447.  
  4448.         /* Proper termination. */
  4449.         if(FLAG_IS_SET(signalsReceived,timerSignal))
  4450.         {
  4451.             WaitIO((struct IORequest *)TimerRequest);
  4452.         }
  4453.     }
  4454.  
  4455.     LEAVE();
  4456. }
  4457.  
  4458. /******************************************************************************/
  4459.  
  4460. char *
  4461. amiga_crypt(char *key,char *salt)
  4462. {
  4463.     char *result;
  4464.  
  4465.     chkabort();
  4466.  
  4467.     ASSERT(key != NULL && salt != NULL);
  4468.  
  4469.     ENTER();
  4470.     SHOWSTRING(key);
  4471.     SHOWVALUE(salt);
  4472.     result = crypt(key,salt);
  4473.  
  4474.     RETURN(result);
  4475.     return(result);
  4476. }
  4477.  
  4478. /******************************************************************************/
  4479.  
  4480. char *
  4481. amiga_getpass(char *prompt)
  4482. {
  4483.     char *result;
  4484.  
  4485.     chkabort();
  4486.  
  4487.     ENTER();
  4488.     SHOWSTRING(prompt);
  4489.     result = getpass(prompt);
  4490.  
  4491.     RETURN(result);
  4492.     return(result);
  4493. }
  4494.  
  4495. /******************************************************************************/
  4496.  
  4497. int
  4498. amiga_setgid(gid_t id)
  4499. {
  4500.     int result;
  4501.  
  4502.     chkabort();
  4503.  
  4504.     ENTER();
  4505.     SHOWVALUE(id);
  4506.     result = setgid(id);
  4507.  
  4508.     RETURN(result);
  4509.     return(result);
  4510. }
  4511.  
  4512. /******************************************************************************/
  4513.  
  4514. int
  4515. amiga_setgroups(int ngroups,gid_t *groups)
  4516. {
  4517.     int result;
  4518.  
  4519.     chkabort();
  4520.  
  4521.     ASSERT(groups != NULL);
  4522.  
  4523.     ENTER();
  4524.     SHOWVALUE(ngroups);
  4525.     SHOWVALUE(groups);
  4526.  
  4527.     result = setgroups(ngroups,groups);
  4528.  
  4529.     RETURN(result);
  4530.     return(result);
  4531. }
  4532.  
  4533. /******************************************************************************/
  4534.  
  4535. gid_t
  4536. amiga_getgid(VOID)
  4537. {
  4538.     int result;
  4539.  
  4540.     chkabort();
  4541.  
  4542.     ENTER();
  4543.     result = getgid();
  4544.  
  4545.     RETURN(result);
  4546.     return(result);
  4547. }
  4548.  
  4549. /******************************************************************************/
  4550.  
  4551. struct group *
  4552. amiga_getgrgid(gid_t gid)
  4553. {
  4554.     struct group *result;
  4555.  
  4556.     chkabort();
  4557.  
  4558.     ENTER();
  4559.     SHOWVALUE(gid);
  4560.  
  4561.     result = getgrgid(gid);
  4562.  
  4563.     RETURN(result);
  4564.     return(result);
  4565. }
  4566.  
  4567. /******************************************************************************/
  4568.  
  4569. struct group *
  4570. amiga_getgrnam(char * name)
  4571. {
  4572.     struct group *result;
  4573.  
  4574.     chkabort();
  4575.  
  4576.     ASSERT(name != NULL);
  4577.  
  4578.     ENTER();
  4579.     SHOWSTRING(name);
  4580.  
  4581.     result = getgrnam(name);
  4582.  
  4583.     RETURN(result);
  4584.     return(result);
  4585. }
  4586.  
  4587. /******************************************************************************/
  4588.  
  4589. int
  4590. amiga_getgroups(int ngroups, gid_t *groups)
  4591. {
  4592.     int result;
  4593.  
  4594.     chkabort();
  4595.  
  4596.     ASSERT(groups != NULL);
  4597.  
  4598.     ENTER();
  4599.     SHOWVALUE(ngroups);
  4600.     SHOWVALUE(groups);
  4601.  
  4602.     result = getgroups(ngroups,groups);
  4603.  
  4604.     RETURN(result);
  4605.     return(result);
  4606. }
  4607.  
  4608. /******************************************************************************/
  4609.  
  4610. struct hostent *
  4611. amiga_gethostbyaddr(char *addr, int len, int type)
  4612. {
  4613.     struct hostent *result;
  4614.  
  4615.     chkabort();
  4616.  
  4617.     ASSERT(addr != NULL);
  4618.  
  4619.     ENTER();
  4620.     SHOWVALUE(addr);
  4621.     SHOWVALUE(len);
  4622.     SHOWVALUE(type);
  4623.  
  4624.     result = gethostbyaddr(addr,len,type);
  4625.  
  4626.     RETURN(result);
  4627.     return(result);
  4628. }
  4629.  
  4630. /******************************************************************************/
  4631.  
  4632. struct hostent *
  4633. amiga_gethostbyname(char *name)
  4634. {
  4635.     struct hostent *result;
  4636.  
  4637.     chkabort();
  4638.  
  4639.     ASSERT(name != NULL);
  4640.  
  4641.     ENTER();
  4642.     SHOWSTRING(name);
  4643.  
  4644.     result = gethostbyname(name);
  4645.  
  4646.     RETURN(result);
  4647.     return(result);
  4648. }
  4649.  
  4650. /******************************************************************************/
  4651.  
  4652. struct netent *
  4653. amiga_getnetbyname(char *name)
  4654. {
  4655.     struct netent *result;
  4656.  
  4657.     chkabort();
  4658.  
  4659.     ASSERT(name != NULL);
  4660.  
  4661.     ENTER();
  4662.     SHOWSTRING(name);
  4663.  
  4664.     result = getnetbyname(name);
  4665.  
  4666.     RETURN(result);
  4667.     return(result);
  4668. }
  4669.  
  4670. /******************************************************************************/
  4671.  
  4672. int
  4673. amiga_gethostname(char *hostname,int size)
  4674. {
  4675.     int result;
  4676.  
  4677.     chkabort();
  4678.  
  4679.     ASSERT(hostname != NULL);
  4680.  
  4681.     ENTER();
  4682.     SHOWVALUE(hostname);
  4683.     SHOWVALUE(size);
  4684.  
  4685.     result = gethostname(hostname,size);
  4686.  
  4687.     if(result == 0)
  4688.         SHOWSTRING(hostname);
  4689.  
  4690.     RETURN(result);
  4691.     return(result);
  4692. }
  4693.  
  4694. /******************************************************************************/
  4695.  
  4696. struct passwd *
  4697. amiga_getpwnam(char *name)
  4698. {
  4699.     struct passwd *result;
  4700.  
  4701.     chkabort();
  4702.  
  4703.     ASSERT(name != NULL);
  4704.  
  4705.     ENTER();
  4706.     SHOWSTRING(name);
  4707.  
  4708.     result = getpwnam(name);
  4709.  
  4710.     RETURN(result);
  4711.     return(result);
  4712. }
  4713.  
  4714. /******************************************************************************/
  4715.  
  4716. struct passwd *
  4717. amiga_getpwuid(uid_t uid)
  4718. {
  4719.     struct passwd *result;
  4720.  
  4721.     chkabort();
  4722.  
  4723.     ENTER();
  4724.     SHOWVALUE(uid);
  4725.  
  4726.     result = getpwuid(uid);
  4727.  
  4728.     RETURN(result);
  4729.     return(result);
  4730. }
  4731.  
  4732. /******************************************************************************/
  4733.  
  4734. uid_t
  4735. amiga_getuid(VOID)
  4736. {
  4737.     uid_t result;
  4738.  
  4739.     chkabort();
  4740.  
  4741.     ENTER();
  4742.  
  4743.     result = getuid();
  4744.  
  4745.     RETURN(result);
  4746.     return(result);
  4747. }
  4748.  
  4749. /******************************************************************************/
  4750.  
  4751. gid_t
  4752. amiga_getegid(VOID)
  4753. {
  4754.     gid_t result;
  4755.  
  4756.     chkabort();
  4757.  
  4758.     ENTER();
  4759.     result = getegid();
  4760.  
  4761.     RETURN(result);
  4762.     return(result);
  4763. }
  4764.  
  4765. /******************************************************************************/
  4766.  
  4767. uid_t
  4768. amiga_geteuid(VOID)
  4769. {
  4770.     uid_t result;
  4771.  
  4772.     chkabort();
  4773.  
  4774.     ENTER();
  4775.  
  4776.     result = geteuid();
  4777.  
  4778.     RETURN(result);
  4779.     return(result);
  4780. }
  4781.  
  4782. /******************************************************************************/
  4783.  
  4784. int
  4785. amiga_initgroups(char *name, gid_t basegroup)
  4786. {
  4787.     int result;
  4788.  
  4789.     chkabort();
  4790.  
  4791.     ASSERT(name != NULL);
  4792.  
  4793.     ENTER();
  4794.     SHOWSTRING(name);
  4795.     SHOWVALUE(basegroup);
  4796.  
  4797.     result = initgroups(name,basegroup);
  4798.  
  4799.     RETURN(result);
  4800.     return(result);
  4801. }
  4802.  
  4803. /******************************************************************************/
  4804.  
  4805. int
  4806. amiga_setuid(uid_t id)
  4807. {
  4808.     int result;
  4809.  
  4810.     chkabort();
  4811.  
  4812.     ENTER();
  4813.     SHOWVALUE(id);
  4814.  
  4815.     result = setuid(id);
  4816.  
  4817.     RETURN(result);
  4818.     return(result);
  4819. }
  4820.  
  4821. /******************************************************************************/
  4822.  
  4823. int
  4824. amiga_umask(int mask)
  4825. {
  4826.     int result;
  4827.  
  4828.     chkabort();
  4829.  
  4830.     ENTER();
  4831.     SHOWVALUE(mask);
  4832.  
  4833.     result = umask(mask);
  4834.  
  4835.     RETURN(result);
  4836.     return(result);
  4837. }
  4838.  
  4839. /******************************************************************************/
  4840.  
  4841. unsigned long
  4842. amiga_inet_addr(char *addr)
  4843. {
  4844.     unsigned long result;
  4845.  
  4846.     chkabort();
  4847.  
  4848.     ASSERT(addr != NULL);
  4849.  
  4850.     ENTER();
  4851.     SHOWSTRING(addr);
  4852.  
  4853.     result = inet_addr(addr);
  4854.  
  4855.     RETURN(result);
  4856.     return(result);
  4857. }
  4858.  
  4859. /******************************************************************************/
  4860.  
  4861. char *
  4862. amiga_inet_ntoa(struct in_addr in)
  4863. {
  4864.     char *result;
  4865.  
  4866.     chkabort();
  4867.  
  4868.     ENTER();
  4869.     SHOWVALUE(in.s_addr);
  4870.  
  4871.     result = Inet_NtoA(in.s_addr);
  4872.     SHOWSTRING(result);
  4873.  
  4874.     RETURN(result);
  4875.     return(result);
  4876. }
  4877.  
  4878. /******************************************************************************/
  4879.  
  4880. int    opterr = 1;
  4881. int    optind = 1;
  4882. int    optopt;
  4883. char * optarg;
  4884.  
  4885. int
  4886. amiga_getopt(int argc, char * argv[], char *opts)
  4887. {
  4888.     STATIC int sp = 1;
  4889.     int c;
  4890.     char *cp;
  4891.  
  4892.     ASSERT(argc > 0 && argv != NULL && opts != NULL);
  4893.  
  4894.     if(sp == 1)
  4895.     {
  4896.         if(optind >= argc || argv[optind][0] != '-' || argv[optind][1] == '\0')
  4897.         {
  4898.             return(EOF);
  4899.         }
  4900.         else if(strcmp(argv[optind], "--") == NULL)
  4901.         {
  4902.             optind++;
  4903.             return(EOF);
  4904.         }
  4905.     }
  4906.  
  4907.     optopt = c = argv[optind][sp];
  4908.     if(c == ':' || (cp=index(opts, c)) == NULL)
  4909.     {
  4910.         if(opterr)
  4911.             fprintf(stderr, "%s%s%c\n", argv[0], ": illegal option -- ", c);
  4912.  
  4913.         if(argv[optind][++sp] == '\0')
  4914.         {
  4915.             optind++;
  4916.             sp = 1;
  4917.         }
  4918.  
  4919.         return('?');
  4920.     }
  4921.  
  4922.     if(*++cp == ':')
  4923.     {
  4924.         if(argv[optind][sp+1] != '\0')
  4925.         {
  4926.             optarg = &argv[optind++][sp+1];
  4927.         }
  4928.         else if(++optind >= argc)
  4929.         {
  4930.             if(opterr)
  4931.                 fprintf(stderr, "%s%s%c\n", argv[0], ": option requires an argument -- ", c);
  4932.  
  4933.             sp = 1;
  4934.             return('?');
  4935.         }
  4936.         else
  4937.         {
  4938.             optarg = argv[optind++];
  4939.         }
  4940.  
  4941.         sp = 1;
  4942.     }
  4943.     else
  4944.     {
  4945.         if(argv[optind][++sp] == '\0')
  4946.         {
  4947.             sp = 1;
  4948.             optind++;
  4949.         }
  4950.  
  4951.         optarg = NULL;
  4952.     }
  4953.  
  4954.     return(c);
  4955. }
  4956.  
  4957. /******************************************************************************/
  4958.  
  4959. /* This comes from util/lib.c */
  4960. STATIC BOOL
  4961. do_match(STRPTR str, STRPTR regexp)
  4962. {
  4963.     STRPTR p;
  4964.  
  4965.     for(p = regexp; (*p) != '\0' && (*str) != '\0' ; NULL)
  4966.     {
  4967.         switch(*p)
  4968.         {
  4969.             case '?':
  4970.  
  4971.                 str++;
  4972.                 p++;
  4973.  
  4974.                 break;
  4975.  
  4976.             /* Look for a character matching the one after the '*' */
  4977.             case '*':
  4978.  
  4979.                 p++;
  4980.  
  4981.                 if((*p) == '\0')
  4982.                     return(TRUE); /* Automatic match */
  4983.  
  4984.                 while((*str) != '\0')
  4985.                 {
  4986.                     while((*str) != '\0' && ToUpper(*p) != ToUpper(*str))
  4987.                         str++;
  4988.  
  4989.                     if(do_match(str,p))
  4990.                         return(TRUE);
  4991.  
  4992.                     if((*str) == '\0')
  4993.                         return(FALSE);
  4994.                     else
  4995.                         str++;
  4996.                 }
  4997.  
  4998.                 return(FALSE);
  4999.  
  5000.             default:
  5001.  
  5002.                 if(ToUpper(*str++) != ToUpper(*p++))
  5003.                     return(FALSE);
  5004.  
  5005.                 break;
  5006.         }
  5007.     }
  5008.  
  5009.     if((*p) == '\0' && (*str) == '\0')
  5010.         return(TRUE);
  5011.  
  5012.     if((*p) == '\0' && str[0] == '.' && str[1] == '\0')
  5013.         return(TRUE);
  5014.  
  5015.     if((*str) == '\0' && (*p) == '?')
  5016.     {
  5017.         while((*p) == '?')
  5018.             p++;
  5019.  
  5020.         return((BOOL)((*p) == '\0'));
  5021.     }
  5022.  
  5023.     if((*str) == '\0' && ((*p) == '*' && p[1] == '\0'))
  5024.         return(TRUE);
  5025.  
  5026.     return(FALSE);
  5027. }
  5028.  
  5029. STATIC VOID
  5030. nstrcpy_blank(const size_t maxSize,char *to,const char *from)
  5031. {
  5032.     size_t len = 0;
  5033.  
  5034.     while((*from) != '\0' && (*from) != ' ' && len < maxSize-1)
  5035.     {
  5036.         (*to++) = (*from++);
  5037.         len++;
  5038.     }
  5039.  
  5040.     (*to) = '\0';
  5041. }
  5042.  
  5043. STATIC VOID
  5044. fill_volume_list(struct List * list)
  5045. {
  5046.     struct DosList * dol;
  5047.  
  5048.     dol = NextDosEntry(LockDosList(LDF_VOLUMES|LDF_READ),
  5049.                                    LDF_VOLUMES|LDF_READ);
  5050.     while(dol != NULL)
  5051.     {
  5052.         /* Does the volume refer to a medium that is right
  5053.          * now present in the drive?
  5054.          */
  5055.         if(dol->dol_Task != NULL)
  5056.         {
  5057.             struct InfoData __aligned id;
  5058.  
  5059.             /* Is there a disk present? */
  5060.             if(DoPkt(dol->dol_Task,ACTION_DISK_INFO,MKBADDR(&id),    0,0,0,0))
  5061.             {
  5062.                 STRPTR name = BADDR(dol->dol_Name);
  5063.                 struct Node * node;
  5064.  
  5065.                 node = malloc(sizeof(*node) + ((int)name[0])+1);
  5066.                 if(node != NULL)
  5067.                 {
  5068.                     /* Copy the name of the volume. */
  5069.                     node->ln_Name = (char *)(node + 1);
  5070.                     strncpy(node->ln_Name,&name[1],name[0]);
  5071.                     node->ln_Name[ name[0] ] = '\0';
  5072.  
  5073.                     AddTail(list,node);
  5074.                 }
  5075.             }
  5076.         }
  5077.  
  5078.         dol = NextDosEntry(dol,LDF_VOLUMES|LDF_READ);
  5079.     }
  5080.  
  5081.     UnLockDosList(LDF_VOLUMES|LDF_READ);
  5082. }
  5083.  
  5084. STATIC int
  5085. deep_scan_drawer(char * drawerName,char * whichPattern,FILE * out)
  5086. {
  5087.     char * originalDrawerName;
  5088.     struct MangleInfo mi;
  5089.     int result = ERROR;
  5090.  
  5091.     originalDrawerName = drawerName;
  5092.     if(MangleName(&drawerName,&mi) == OK)
  5093.     {
  5094.         BPTR dirLock;
  5095.  
  5096.         dirLock = Lock(drawerName,SHARED_LOCK);
  5097.         if(dirLock != ZERO)
  5098.         {
  5099.             struct FileInfoBlock __aligned fib;
  5100.  
  5101.             if(Examine(dirLock,&fib))
  5102.             {
  5103.                 struct AnchorPath * ap;
  5104.  
  5105.                 ap = malloc(sizeof(*ap) + MAX_FILENAME_LEN);
  5106.                 if(ap != NULL)
  5107.                 {
  5108.                     BOOL stopped = FALSE;
  5109.                     BPTR oldDir;
  5110.                     LONG error;
  5111.  
  5112.                     oldDir = CurrentDir(dirLock);
  5113.  
  5114.                     memset(ap,0,sizeof(*ap) + MAX_FILENAME_LEN);
  5115.                     ap->ap_Strlen        = MAX_FILENAME_LEN;
  5116.                     ap->ap_BreakBits    = SIGBREAKF_CTRL_C;
  5117.  
  5118.                     if((error = MatchFirst("",ap)) == OK)
  5119.                     {
  5120.                         BOOL check;
  5121.  
  5122.                         do
  5123.                         {
  5124.                             D(("checking |%s|",ap->ap_Buf));
  5125.  
  5126.                             check = TRUE;
  5127.  
  5128.                             if(FIB_IS_FILE(&ap->ap_Info))
  5129.                             {
  5130.                                 SHOWMSG("this is a file");
  5131.                             }
  5132.                             else
  5133.                             {
  5134.                                 SHOWMSG("this is a drawer");
  5135.  
  5136.                                 if(FLAG_IS_CLEAR(ap->ap_Flags,APF_DIDDIR))
  5137.                                 {
  5138.                                     SET_FLAG(ap->ap_Flags,APF_DODIR);
  5139.                                 }
  5140.                                 else
  5141.                                 {
  5142.                                     CLEAR_FLAG(ap->ap_Flags,APF_DIDDIR);
  5143.                                     check = FALSE;
  5144.                                 }
  5145.                             }
  5146.  
  5147.                             if(check)
  5148.                             {
  5149.                                 SHOWSTRING(ap->ap_Info.fib_FileName);
  5150.  
  5151.                                 if(do_match(ap->ap_Info.fib_FileName,whichPattern))
  5152.                                 {
  5153.                                     D(("Output |%s/%s|",originalDrawerName,ap->ap_Buf));
  5154.                                     if(fprintf(out,"%s/%s\n",originalDrawerName,ap->ap_Buf) < 0)
  5155.                                     {
  5156.                                         stopped = TRUE;
  5157.                                         break;
  5158.                                     }
  5159.                                 }
  5160.                                 else
  5161.                                 {
  5162.                                     SHOWMSG("but its name does not match");
  5163.                                 }
  5164.                             }
  5165.                         }
  5166.                         while((error = MatchNext(ap)) == OK);
  5167.                     }
  5168.  
  5169.                     MatchEnd(ap);
  5170.  
  5171.                     CurrentDir(oldDir);
  5172.  
  5173.                     if(NOT stopped)
  5174.                     {
  5175.                         if(error == ERROR_NO_MORE_ENTRIES)
  5176.                         {
  5177.                             result = OK;
  5178.                         }
  5179.                         else if(error == ERROR_BREAK)
  5180.                         {
  5181.                             /* Don't do anything; we are going
  5182.                              * to delete the file anyway.
  5183.                              */
  5184.                         }
  5185.                         else
  5186.                         {
  5187.                             SetIoErr(error);
  5188.                             MapIoErrToErrno();
  5189.                         }
  5190.                     }
  5191.  
  5192.                     free(ap);
  5193.                 }
  5194.                 else
  5195.                 {
  5196.                     errno = ENOMEM;
  5197.                 }
  5198.             }
  5199.             else
  5200.             {
  5201.                 MapIoErrToErrno();
  5202.             }
  5203.  
  5204.             UnLock(dirLock);
  5205.         }
  5206.         else
  5207.         {
  5208.             MapIoErrToErrno();
  5209.         }
  5210.  
  5211.         UnmangleName(&drawerName,&mi);
  5212.     }
  5213.  
  5214.     return(result);
  5215. }
  5216.  
  5217. int
  5218. amiga_system(char *cmd)
  5219. {
  5220.     char redirectionFileBuffer[MAX_FILENAME_LEN];
  5221.     char *redirectionFile = redirectionFileBuffer;
  5222.     struct MangleInfo mi;
  5223.     int result = ERROR;
  5224.     char *stop;
  5225.     char *options;
  5226.     char *cmdName;
  5227.     int cmdLen,i;
  5228.     int quoteCount;
  5229.  
  5230.     chkabort();
  5231.  
  5232.     ASSERT(cmd != NULL);
  5233.  
  5234.     ENTER();
  5235.     SHOWSTRING(cmd);
  5236.  
  5237.     /* Handle two special cases for the smb client program,
  5238.      * which for reasons unknown to me resorts to calling
  5239.      * the Unix "ls" and "find" programs to collect lists
  5240.      * of files.
  5241.      *
  5242.      * The commands to watch for take the following forms:
  5243.      *
  5244.      *    /bin/ls file_to_list > output_filename
  5245.      *    find directory_to_list -name "pattern_to_list" -print > output_filename
  5246.      */
  5247.     stop = cmd;
  5248.     while((*stop) != ' ' && (*stop) != '\0')
  5249.         stop++;
  5250.  
  5251.     /* This will point behind the command name,
  5252.      * to the beginning of the list of options,
  5253.      * if any.
  5254.      */
  5255.     options = stop;
  5256.     while((*options) == ' ')
  5257.         options++;
  5258.  
  5259.     /* Now go and isolate the command name. */
  5260.     cmdName = cmd;
  5261.     cmdLen = stop-cmd;
  5262.     for(i = cmdLen - 1 ; i >= 0 ; i--)
  5263.     {
  5264.         if(cmd[i] == '/' || cmd[i] == ':')
  5265.         {
  5266.             cmdName = &cmd[i+1];
  5267.  
  5268.             stop = cmdName;
  5269.             while((*stop) != ' ' && (*stop) != '\0')
  5270.                 stop++;
  5271.  
  5272.             cmdLen = stop-cmdName;
  5273.  
  5274.             break;
  5275.         }
  5276.     }
  5277.  
  5278.     /* We have isolated the command name, now
  5279.      * find the redirection file name.
  5280.      */
  5281.     quoteCount = 0;
  5282.     strcpy(redirectionFile,"");
  5283.     for(i = 0 ; i < strlen(cmd) ; i++)
  5284.     {
  5285.         if(cmd[i] == '\"')
  5286.             quoteCount = (1-quoteCount);
  5287.  
  5288.         if(cmd[i] == '>' && quoteCount == 0)
  5289.         {
  5290.             char * from;
  5291.  
  5292.             from = &cmd[i+1];
  5293.             while((*from) == ' ')
  5294.                 from++;
  5295.  
  5296.             /* Note that we rely upon the
  5297.              * redirection file name not to contain
  5298.              * quote or escape characters.
  5299.              */
  5300.             nstrcpy_blank(sizeof(redirectionFileBuffer),redirectionFile,from);
  5301.             break;
  5302.         }
  5303.     }
  5304.  
  5305.     /* Now check which command we got. */
  5306.     if(cmdLen == 2 && Strnicmp(cmdName,"ls",2) == SAME)
  5307.     {
  5308.         char localDirName[MAX_FILENAME_LEN];
  5309.         char * dirName;
  5310.  
  5311.         dirName = ".";
  5312.  
  5313.         if(TranslateRelativePath(&dirName,localDirName,sizeof(localDirName)) == OK)
  5314.         {
  5315.             char whichPatternBuffer[MAX_FILENAME_LEN];
  5316.             char *whichPattern = whichPatternBuffer;
  5317.             BOOL oldAllowBreak = AllowBreak;
  5318.  
  5319.             /* We don't want to be interrupted. */
  5320.             AllowBreak = FALSE;
  5321.  
  5322.             /* Now find the pattern to use. */
  5323.             nstrcpy_blank(sizeof(whichPatternBuffer),whichPattern,options);
  5324.  
  5325.             SHOWMSG("doing `ls'");
  5326.             SHOWSTRING(whichPattern);
  5327.             SHOWSTRING(redirectionFile);
  5328.  
  5329.             /* What happens next is that the contents of the
  5330.              * current directory are scanned. All names
  5331.              * that match the given pattern are stored in the
  5332.              * redirection file.
  5333.              */
  5334.  
  5335.             if(MangleName(&redirectionFile,&mi) == OK)
  5336.             {
  5337.                 FILE * out;
  5338.  
  5339.                 ForbidDOS();
  5340.  
  5341.                 out = fopen(redirectionFile,"wb");
  5342.                 if(out != NULL)
  5343.                 {
  5344.                     SHOWSTRING(localDirName);
  5345.  
  5346.                     if(strcmp(localDirName,"/") == SAME)
  5347.                     {
  5348.                         struct List list;
  5349.                         struct Node * node;
  5350.  
  5351.                         SHOWMSG("listing volumes");
  5352.  
  5353.                         NewList(&list);
  5354.  
  5355.                         fill_volume_list(&list);
  5356.  
  5357.                         while((node = RemHead(&list)) != NULL)
  5358.                         {
  5359.                             D(("checking '%s'",node->ln_Name));
  5360.  
  5361.                             if(do_match(node->ln_Name,whichPattern))
  5362.                             {
  5363.                                 SHOWMSG(">>> matches");
  5364.  
  5365.                                 if(fprintf(out,"%s\n",node->ln_Name) < 0)
  5366.                                     break;
  5367.                             }
  5368.                             else
  5369.                             {
  5370.                                 SHOWMSG(">>> does not match");
  5371.                             }
  5372.  
  5373.                             free(node);
  5374.                         }
  5375.  
  5376.                         while((node = RemHead(&list)) != NULL)
  5377.                             free(node);
  5378.                     }
  5379.                     else
  5380.                     {
  5381.                         BPTR dirLock;
  5382.  
  5383.                         SHOWMSG("listing drawers");
  5384.  
  5385.                         dirLock = Lock("",SHARED_LOCK);
  5386.                         if(dirLock != ZERO)
  5387.                         {
  5388.                             struct FileInfoBlock __aligned fib;
  5389.  
  5390.                             if(Examine(dirLock,&fib))
  5391.                             {
  5392.                                 BOOL stopped = FALSE;
  5393.  
  5394.                                 while(ExNext(dirLock,&fib))
  5395.                                 {
  5396.                                     D(("checking '%s'",fib.fib_FileName));
  5397.  
  5398.                                     if(do_match(fib.fib_FileName,whichPattern))
  5399.                                     {
  5400.                                         SHOWMSG(">>> matches");
  5401.  
  5402.                                         if(fprintf(out,"%s\n",fib.fib_FileName) < 0)
  5403.                                         {
  5404.                                             stopped = TRUE;
  5405.                                             break;
  5406.                                         }
  5407.                                     }
  5408.                                     else
  5409.                                     {
  5410.                                         SHOWMSG(">>> does not match");
  5411.                                     }
  5412.                                 }
  5413.  
  5414.                                 if(NOT stopped)
  5415.                                 {
  5416.                                     LONG error = IoErr();
  5417.  
  5418.                                     if(error == ERROR_NO_MORE_ENTRIES)
  5419.                                     {
  5420.                                         result = OK;
  5421.                                     }
  5422.                                     else
  5423.                                     {
  5424.                                         SetIoErr(error);
  5425.                                         MapIoErrToErrno();
  5426.                                     }
  5427.                                 }
  5428.                             }
  5429.                             else
  5430.                             {
  5431.                                 MapIoErrToErrno();
  5432.                             }
  5433.  
  5434.                             UnLock(dirLock);
  5435.                         }
  5436.                         else
  5437.                         {
  5438.                             MapIoErrToErrno();
  5439.                         }
  5440.                     }
  5441.  
  5442.                     fclose(out);
  5443.  
  5444.                     if(result != OK)
  5445.                         DeleteFile(redirectionFile);
  5446.                 }
  5447.  
  5448.                 PermitDOS();
  5449.  
  5450.                 UnmangleName(&cmd,&mi);
  5451.             }
  5452.  
  5453.             AllowBreak = oldAllowBreak;
  5454.         }
  5455.     }
  5456.     else if (cmdLen == 4 && Strnicmp(cmdName,"find",4) == SAME)
  5457.     {
  5458.         char whichDrawerBuffer[MAX_FILENAME_LEN];
  5459.         char * whichDrawer = whichDrawerBuffer;
  5460.         char whichPattern[MAX_FILENAME_LEN];
  5461.         const int _nameLen = strlen("-name");
  5462.         BOOL oldAllowBreak = AllowBreak;
  5463.         struct List list;
  5464.         struct Node * node;
  5465.  
  5466.         NewList(&list);
  5467.  
  5468.         /* We don't want to be interrupted. */
  5469.         AllowBreak = FALSE;
  5470.  
  5471.         /* Now find the drawer to examine. */
  5472.         nstrcpy_blank(sizeof(whichDrawerBuffer),whichDrawer,options);
  5473.  
  5474.         /* Find the pattern to search for. */
  5475.         strcpy(whichPattern,"");
  5476.         for(i = 0 ; i < strlen(options) ; i++)
  5477.         {
  5478.             if(Strnicmp(&options[i],"-name",_nameLen) == SAME)
  5479.             {
  5480.                 const int maxLen = sizeof(whichPattern)-1;
  5481.                 int whichPatternLen;
  5482.                 int escapeCount;
  5483.                 int quoteCount;
  5484.                 char * from;
  5485.                 char * to;
  5486.  
  5487.                 /* `from' should now point straight at the
  5488.                  * search pattern, which is probably enclosed
  5489.                  * in quote characters.
  5490.                  */
  5491.                 from = &options[i+_nameLen];
  5492.                 while((*from) == ' ')
  5493.                     from++;
  5494.  
  5495.                 to = whichPattern;
  5496.                 whichPatternLen = 0;
  5497.                 quoteCount = 0;
  5498.                 escapeCount = 0;
  5499.                 while((*from) != '\0' && whichPatternLen < maxLen)
  5500.                 {
  5501.                     if(escapeCount != 0)
  5502.                     {
  5503.                         (*to++) = (*from++);
  5504.                         whichPatternLen++;
  5505.                         escapeCount = 0;
  5506.                     }
  5507.                     else if((*from) == '\\')
  5508.                     {
  5509.                         escapeCount = (1-escapeCount);
  5510.                         from++;
  5511.                     }
  5512.                     else if ((*from) == '\"')
  5513.                     {
  5514.                         quoteCount = (1-quoteCount);
  5515.                         from++;
  5516.                     }
  5517.                     else
  5518.                     {
  5519.                         if((*from) == ' ' && quoteCount == 0)
  5520.                         {
  5521.                             break;
  5522.                         }
  5523.                         else
  5524.                         {
  5525.                             (*to++) = (*from++);
  5526.                             whichPatternLen++;
  5527.                         }
  5528.                     }
  5529.                 }
  5530.  
  5531.                 (*to) = '\0';
  5532.             }
  5533.         }
  5534.  
  5535.         SHOWMSG("doing `find'");
  5536.         SHOWSTRING(whichDrawer);
  5537.         SHOWSTRING(whichPattern);
  5538.         SHOWSTRING(redirectionFile);
  5539.  
  5540.         /* Things are a little bit more complicated here. The
  5541.          * "find" program scans recursively through a directory
  5542.          * tree. We emulate this behaviour by having the MatchFirst/MatchNext
  5543.          * routines iterate through the directory tree. The
  5544.          * name of every file found is matched against the given
  5545.          * pattern and, if necessary, written to the redirection
  5546.          * file. Note that matching is performed only on the
  5547.          * file name, not on the entire path.
  5548.          */
  5549.  
  5550.         if(MangleName(&redirectionFile,&mi) == OK)
  5551.         {
  5552.             FILE * out;
  5553.  
  5554.             ForbidDOS();
  5555.  
  5556.             out = fopen(redirectionFile,"wb");
  5557.             if(out != NULL)
  5558.             {
  5559.                 char localDirName[MAX_FILENAME_LEN];
  5560.                 char * dirName;
  5561.  
  5562.                 dirName = whichDrawer;
  5563.  
  5564.                 if(TranslateRelativePath(&dirName,localDirName,sizeof(localDirName)) == OK)
  5565.                 {
  5566.                     D(("listing path '%s'",dirName));
  5567.  
  5568.                     if(strcmp(dirName,"/") == SAME)
  5569.                     {
  5570.                         SHOWMSG("checking all 'drawers' in the fake root");
  5571.  
  5572.                         fill_volume_list(&list);
  5573.  
  5574.                         while((node = RemHead(&list)) != NULL)
  5575.                         {
  5576.                             strcpy(localDirName,"/");
  5577.                             strcat(localDirName,node->ln_Name);
  5578.                             free(node);
  5579.  
  5580.                             D(("checking '%s'",localDirName));
  5581.  
  5582.                             result = deep_scan_drawer(localDirName,whichPattern,out);
  5583.                             if(result != OK)
  5584.                                 break;
  5585.                         }
  5586.  
  5587.                         while((node = RemHead(&list)) != NULL)
  5588.                             free(node);
  5589.                     }
  5590.                     else
  5591.                     {
  5592.                         SHOWMSG("checking only a local drawer");
  5593.  
  5594.                         result = deep_scan_drawer(dirName,whichPattern,out);
  5595.                     }
  5596.                 }
  5597.  
  5598.                 fclose(out);
  5599.  
  5600.                 if(result != OK)
  5601.                     DeleteFile(redirectionFile);
  5602.             }
  5603.  
  5604.             PermitDOS();
  5605.  
  5606.             UnmangleName(&cmd,&mi);
  5607.         }
  5608.  
  5609.         AllowBreak = oldAllowBreak;
  5610.     }
  5611.     else
  5612.     {
  5613.         if(MangleName(&cmd,&mi) == OK)
  5614.         {
  5615.             ForbidDOS();
  5616.             result = system(cmd);
  5617.             PermitDOS();
  5618.  
  5619.             UnmangleName(&cmd,&mi);
  5620.         }
  5621.     }
  5622.  
  5623.     RETURN(result);
  5624.     return(result);
  5625. }
  5626.  
  5627. /******************************************************************************/
  5628.  
  5629. int
  5630. amiga_fork(VOID)    /* dummy */
  5631. {
  5632.     int result;
  5633.  
  5634.     chkabort();
  5635.  
  5636.     ENTER();
  5637.  
  5638.     result = ERROR;
  5639.     errno = ENOSYS;
  5640.  
  5641.     RETURN(result);
  5642.     return(result);
  5643. }
  5644.  
  5645. /******************************************************************************/
  5646.  
  5647. STATIC BOOL
  5648. SetFileSocket(FILE *stream,int sockfd)
  5649. {
  5650.     struct UFB * ufb;
  5651.     BOOL success = FALSE;
  5652.  
  5653.     ASSERT(stream != NULL);
  5654.  
  5655.     ENTER();
  5656.  
  5657.     /* Check which buffer the file
  5658.      * is attached to.
  5659.      */
  5660.     ufb = chkufb(fileno(stream));
  5661.     if(ufb != NULL)
  5662.     {
  5663.         SHOWVALUE(ufb);
  5664.  
  5665.         /* Save the file handle. */
  5666.         if(SaveDescriptor(ufb))
  5667.         {
  5668.             /* And put the socket in its place. */
  5669.             ufb->ufbfh = sockfd;
  5670.             SET_FLAG(ufb->ufbflg,UFB_IS_SOCKET);
  5671.  
  5672.             success = TRUE;
  5673.         }
  5674.     }
  5675.     else
  5676.     {
  5677.         SHOWMSG("no ufb");
  5678.     }
  5679.  
  5680.     RETURN(success);
  5681.     return(success);
  5682. }
  5683.  
  5684. STATIC VOID
  5685. DaemonInit(VOID)
  5686. {
  5687.     struct DaemonMessage * dm;
  5688.     int sock;
  5689.  
  5690.     ENTER();
  5691.  
  5692.     /* This routine is called when the program starts up.
  5693.      * If it was launched by the INet super server, this
  5694.      * program will run as a daemon. We pick up its
  5695.      * socket input stream and attach it to our stdio
  5696.      * streams.
  5697.      */
  5698.     dm = (struct DaemonMessage *)((struct Process *)FindTask(NULL))->pr_ExitData;
  5699.     if(dm != NULL)
  5700.     {
  5701.         sock = ObtainSocket(dm->dm_ID,dm->dm_Family,dm->dm_Type,0);
  5702.         if(sock != -1)
  5703.         {
  5704.             BOOL success = FALSE;
  5705.             int sock_stdin;
  5706.             int sock_stdout;
  5707.             int sock_stderr;
  5708.  
  5709.             sock_stdin    = Dup2Socket(sock,-1);
  5710.             sock_stdout    = Dup2Socket(sock,-1);
  5711.             sock_stderr    = Dup2Socket(sock,-1);
  5712.  
  5713.             if(sock_stdin != -1 && sock_stdout != -1 && sock_stderr != -1)
  5714.             {
  5715.                 SHOWMSG("got all sockets");
  5716.  
  5717.                 D(("stdin  = sock %ld",sock_stdin));
  5718.                 D(("stdout = sock %ld",sock_stdout));
  5719.                 D(("stderr = sock %ld",sock_stderr));
  5720.  
  5721.                 if(SetFileSocket(stdin,sock_stdin) &&
  5722.                    SetFileSocket(stdout,sock_stdout) &&
  5723.                    SetFileSocket(stderr,sock_stderr))
  5724.                 {
  5725.                     SHOWMSG("and all streams are initialized");
  5726.  
  5727.                     success = TRUE;
  5728.                 }
  5729.                 else
  5730.                 {
  5731.                     SHOWMSG("failed to initialize streams");
  5732.                 }
  5733.             }
  5734.             else
  5735.             {
  5736.                 SHOWMSG("didn't get the sockets");
  5737.             }
  5738.  
  5739.             if(NO success)
  5740.             {
  5741.                 if(sock_stdin != -1)
  5742.                     CloseSocket(sock_stdin);
  5743.  
  5744.                 if(sock_stdout != -1)
  5745.                     CloseSocket(sock_stdout);
  5746.  
  5747.                 if(sock_stderr != -1)
  5748.                     CloseSocket(sock_stderr);
  5749.             }
  5750.         }
  5751.         else
  5752.         {
  5753.             SHOWMSG("no socket");
  5754.         }
  5755.     }
  5756.     else
  5757.     {
  5758.         SHOWMSG("No daemon message");
  5759.     }
  5760.  
  5761.     LEAVE();
  5762. }
  5763.  
  5764. /******************************************************************************/
  5765.  
  5766. VOID
  5767. __tzset(VOID)
  5768. {
  5769.     STATIC char TimeZoneName[20] = "";
  5770.  
  5771.     /* This routine sets up the internal
  5772.      * time zone variable according to
  5773.      * the local settings.
  5774.      */
  5775.     if(STRING_IS_EMPTY(TimeZoneName))
  5776.     {
  5777.         int hoursWest = MinutesWest / 60;
  5778.  
  5779.         if(hoursWest >= 0)
  5780.             sprintf(TimeZoneName,"GMT+%02d", hoursWest);
  5781.         else
  5782.             sprintf(TimeZoneName,"GMT-%02d",-hoursWest);
  5783.     }
  5784.  
  5785.     _TZ = TimeZoneName;
  5786. }
  5787.  
  5788. /******************************************************************************/
  5789.  
  5790. time_t
  5791. time(time_t *timeptr)
  5792. {
  5793.     time_t currentTime;
  5794.     struct timeval tv;
  5795.  
  5796.     chkabort();
  5797.  
  5798.     GetSysTime((APTR)&tv);
  5799.  
  5800.     currentTime = UNIX_TIME_OFFSET + tv.tv_secs + 60*MinutesWest;    /* translate from local time to UTC */
  5801.  
  5802.     if(timeptr != NULL)
  5803.         (*timeptr) = currentTime;
  5804.  
  5805.     return(currentTime);
  5806. }
  5807.  
  5808. /******************************************************************************/
  5809.  
  5810. STATIC struct tm *
  5811. ConvertTime(ULONG seconds)
  5812. {
  5813.     STATIC struct tm tm;
  5814.     struct ClockData clockData;
  5815.     ULONG delta;
  5816.  
  5817.     chkabort();
  5818.  
  5819.     Amiga2Date(seconds,&clockData);
  5820.  
  5821.     tm.tm_sec    = clockData.sec;
  5822.     tm.tm_min    = clockData.min;
  5823.     tm.tm_hour    = clockData.hour;
  5824.     tm.tm_mday    = clockData.mday;
  5825.     tm.tm_mon    = clockData.month - 1;
  5826.     tm.tm_year    = clockData.year - 1900;
  5827.     tm.tm_wday    = clockData.wday;
  5828.     tm.tm_isdst    = 0;
  5829.  
  5830.     clockData.mday    = 1;
  5831.     clockData.month    = 1;
  5832.  
  5833.     delta = Date2Amiga(&clockData);
  5834.  
  5835.     tm.tm_yday = (seconds - delta) / (24*60*60);
  5836.  
  5837.     return(&tm);
  5838. }
  5839.  
  5840. struct tm *
  5841. gmtime(const time_t *t)
  5842. {
  5843.     struct tm * result;
  5844.     ULONG seconds;
  5845.  
  5846.     if((*t) < UNIX_TIME_OFFSET)
  5847.         seconds = 0;
  5848.     else
  5849.         seconds = (*t) - UNIX_TIME_OFFSET;
  5850.  
  5851.     result = ConvertTime(seconds);
  5852.  
  5853.     return(result);
  5854. }
  5855.  
  5856. struct tm *
  5857. localtime(const time_t *t)
  5858. {
  5859.     struct tm * result;
  5860.     ULONG seconds;
  5861.  
  5862.     if((*t) < (UNIX_TIME_OFFSET + 60*MinutesWest))
  5863.         seconds = 0;
  5864.     else
  5865.         seconds = (*t) - (UNIX_TIME_OFFSET + 60*MinutesWest);    /* translate from UTC to local time */
  5866.  
  5867.     result = ConvertTime(seconds);
  5868.  
  5869.     return(result);
  5870. }
  5871.  
  5872. /******************************************************************************/
  5873.  
  5874. int
  5875. amiga_strcasecmp(char *a,char *b)
  5876. {
  5877.     int result;
  5878.  
  5879.     ASSERT(a != NULL && b != NULL);
  5880.  
  5881.     result = Stricmp((STRPTR)a,b);
  5882.  
  5883.     return(result);
  5884. }
  5885.  
  5886. int
  5887. amiga_strncasecmp(char *a,char *b,int len)
  5888. {
  5889.     int result;
  5890.  
  5891.     ASSERT(a != NULL && b != NULL);
  5892.  
  5893.     result = Strnicmp(a,b,len);
  5894.  
  5895.     return(result);
  5896. }
  5897.  
  5898. /******************************************************************************/
  5899.  
  5900. VOID
  5901. (*amiga_signal(int which,VOID (* action)(int)))(int)
  5902. {
  5903.     VOID (* result)(int);
  5904.  
  5905.     chkabort();
  5906.  
  5907.     ENTER();
  5908.  
  5909.     if(SIGABRT <= which && which <= SIGTERM)
  5910.         result = signal(which,action);
  5911.     else
  5912.         result = SIG_DFL;
  5913.  
  5914.     RETURN(result);
  5915.     return(result);
  5916. }
  5917.  
  5918. /******************************************************************************/
  5919.  
  5920. VOID
  5921. amiga_alarm(int seconds)    /* dummy */
  5922. {
  5923.     chkabort();
  5924.  
  5925.     ENTER();
  5926.  
  5927.     LEAVE();
  5928. }
  5929.  
  5930. /******************************************************************************/
  5931.  
  5932. int
  5933. amiga_waitpid(pid_t pid,int *status,int options)    /* dummy */
  5934. {
  5935.     int result;
  5936.  
  5937.     chkabort();
  5938.  
  5939.     ENTER();
  5940.  
  5941.     result = ERROR;
  5942.     errno = ENOSYS;
  5943.  
  5944.     RETURN(result);
  5945.     return(result);
  5946. }
  5947.  
  5948. /******************************************************************************/
  5949.  
  5950. long
  5951. amiga_setsid(VOID)
  5952. {
  5953.     long result;
  5954.  
  5955.     chkabort();
  5956.  
  5957.     ENTER();
  5958.  
  5959.     result = (long)setsid();
  5960.  
  5961.     RETURN(result);
  5962.     return(result);
  5963. }
  5964.  
  5965. /******************************************************************************/
  5966.  
  5967. int
  5968. amiga_setreuid(uid_t real, uid_t eff)
  5969. {
  5970.     int result;
  5971.  
  5972.     chkabort();
  5973.  
  5974.     ENTER();
  5975.  
  5976.     result = setreuid(real,eff);
  5977.  
  5978.     RETURN(result);
  5979.     return(result);
  5980. }
  5981.  
  5982. /******************************************************************************/
  5983.  
  5984. int
  5985. amiga_setregid(gid_t real, gid_t eff)
  5986. {
  5987.     int result;
  5988.  
  5989.     chkabort();
  5990.  
  5991.     ENTER();
  5992.  
  5993.     result = setregid(real,eff);
  5994.  
  5995.     RETURN(result);
  5996.     return(result);
  5997. }
  5998.  
  5999. /******************************************************************************/
  6000.  
  6001. int
  6002. amiga_getsockname(int sockfd,struct sockaddr *name,int *namelen)
  6003. {
  6004.     struct UFB * ufb;
  6005.     int result = ERROR;
  6006.  
  6007.     chkabort();
  6008.  
  6009.     ASSERT(name != NULL && namelen != NULL);
  6010.  
  6011.     ENTER();
  6012.  
  6013.     ufb = chkufb(sockfd);
  6014.     if(ufb != NULL && FLAG_IS_SET(ufb->ufbflg,UFB_IS_SOCKET))
  6015.         result = getsockname(ufb->ufbfh,name,(LONG *)namelen);
  6016.     else
  6017.         errno = ENOTSOCK;
  6018.  
  6019.     RETURN(result);
  6020.     return(result);
  6021. }
  6022.  
  6023. /******************************************************************************/
  6024.  
  6025. int
  6026. amiga_statfs(char *name,struct statfs *f)
  6027. {
  6028.     char localName[MAX_FILENAME_LEN];
  6029.     int result = ERROR;
  6030.  
  6031.     chkabort();
  6032.  
  6033.     ASSERT(name != NULL && f != NULL);
  6034.  
  6035.     ENTER();
  6036.  
  6037.     SHOWSTRING(name);
  6038.     SHOWVALUE(f);
  6039.  
  6040.     if(TranslateRelativePath(&name,localName,sizeof(localName)) == OK)
  6041.     {
  6042.         /* Make up something for the virtual root directory. */
  6043.         if(strcmp(name,"/") == SAME)
  6044.         {
  6045.             memset(f,0,sizeof(*f));
  6046.  
  6047.             f->f_fsize = 512;
  6048.  
  6049.             /* Try to reuse the data from our last scan. */
  6050.             if(RootBlocks > 0 && RootBlocksUsed > 0)
  6051.             {
  6052.                 f->f_blocks    = RootBlocks;
  6053.                 f->f_bfree    = RootBlocks - RootBlocksUsed;
  6054.             }
  6055.             else
  6056.             {
  6057.                 f->f_blocks    = 0x7FFFFFFF/f->f_fsize;
  6058.                 f->f_bfree    = f->f_blocks - 1;
  6059.             }
  6060.  
  6061.             f->f_bsize    = f->f_fsize;
  6062.             f->f_bavail    = f->f_bfree;
  6063.  
  6064.             SHOWVALUE(f->f_fsize);
  6065.             SHOWVALUE(f->f_bsize);
  6066.             SHOWVALUE(f->f_blocks);
  6067.             SHOWVALUE(f->f_bfree);
  6068.             SHOWVALUE(f->f_bavail);
  6069.  
  6070.             result = OK;
  6071.         }
  6072.         else
  6073.         {
  6074.             struct MangleInfo mi;
  6075.             BPTR fileLock;
  6076.  
  6077.             if(MangleName(&name,&mi) == OK)
  6078.             {
  6079.                 ForbidDOS();
  6080.  
  6081.                 fileLock = Lock(name,SHARED_LOCK);
  6082.                 if(fileLock != ZERO)
  6083.                 {
  6084.                     struct InfoData __aligned id;
  6085.  
  6086.                     if(Info(fileLock,&id))
  6087.                     {
  6088.                         memset(f,0,sizeof(*f));
  6089.  
  6090.                         /* Make sure that these never drop to zero. */
  6091.                         if(id.id_NumBlocks == 0)
  6092.                             id.id_NumBlocks = 1;
  6093.  
  6094.                         if(id.id_BytesPerBlock == 0)
  6095.                             id.id_BytesPerBlock = 512;
  6096.  
  6097.                         f->f_fsize    = id.id_BytesPerBlock;                        /* fundamental file system block size */
  6098.                         f->f_blocks    = id.id_NumBlocks;                            /* total data blocks in file system */
  6099.                         f->f_bfree    = id.id_NumBlocks - id.id_NumBlocksUsed;    /* free blocks in fs */
  6100.                         f->f_bsize    = f->f_fsize;                                /* optimal transfer block size */
  6101.                         f->f_bavail    = f->f_bfree;                                /* free blocks avail to non-superuser */
  6102.  
  6103.                         SHOWVALUE(f->f_fsize);
  6104.                         SHOWVALUE(f->f_bsize);
  6105.                         SHOWVALUE(f->f_blocks);
  6106.                         SHOWVALUE(f->f_bfree);
  6107.                         SHOWVALUE(f->f_bavail);
  6108.  
  6109.                         result = OK;
  6110.                     }
  6111.                     else
  6112.                     {
  6113.                         MapIoErrToErrno();
  6114.                     }
  6115.  
  6116.                     UnLock(fileLock);
  6117.                 }
  6118.                 else
  6119.                 {
  6120.                     MapIoErrToErrno();
  6121.                 }
  6122.  
  6123.                 PermitDOS();
  6124.  
  6125.                 UnmangleName(&name,&mi);
  6126.             }
  6127.         }
  6128.     }
  6129.  
  6130.     RETURN(result);
  6131.     return(result);
  6132. }
  6133.  
  6134. /******************************************************************************/
  6135.  
  6136. int
  6137. amiga_execl(char *path,char *arg,...)    /* dummy */
  6138. {
  6139.     int result;
  6140.  
  6141.     chkabort();
  6142.  
  6143.     ENTER();
  6144.  
  6145.     result = ERROR;
  6146.     errno = ENOSYS;
  6147.  
  6148.     RETURN(result);
  6149.     return(result);
  6150. }
  6151.  
  6152. /******************************************************************************/
  6153.  
  6154. char *
  6155. amiga_strerror(int error)
  6156. {
  6157.     struct TagItem tags[2];
  6158.     char *result;
  6159.  
  6160.     chkabort();
  6161.  
  6162.     ENTER();
  6163.  
  6164.     tags[0].ti_Tag    = SBTM_GETVAL(SBTC_ERRNOSTRPTR);
  6165.     tags[0].ti_Data    = error;
  6166.     tags[1].ti_Tag    = TAG_END;
  6167.  
  6168.     SocketBaseTagList(tags);
  6169.  
  6170.     result = (char *)tags[0].ti_Data;
  6171.  
  6172.     RETURN(result);
  6173.     return(result);
  6174. }
  6175.  
  6176. /******************************************************************************/
  6177.  
  6178. int
  6179. amiga_access(char *name,int modes)
  6180. {
  6181.     struct MangleInfo mi;
  6182.     int result = ERROR;
  6183.  
  6184.     chkabort();
  6185.  
  6186.     ASSERT(name != NULL);
  6187.  
  6188.     ENTER();
  6189.  
  6190.     if(MangleName(&name,&mi) == OK)
  6191.     {
  6192.         ForbidDOS();
  6193.         result = access(name,modes);
  6194.         PermitDOS();
  6195.  
  6196.         UnmangleName(&name,&mi);
  6197.     }
  6198.  
  6199.     RETURN(result);
  6200.     return(result);
  6201. }
  6202.  
  6203. /******************************************************************************/
  6204.  
  6205. STATIC VOID
  6206. MapIoErrToErrno(VOID)
  6207. {
  6208.     /* This routine maps AmigaDOS error codes to
  6209.      * Unix error codes, as far as this is possible.
  6210.      * This table contains AmigaDOS error codes
  6211.      * the emulated routines won't generate. I have
  6212.      * included them for the sake of completeness.
  6213.      */
  6214.     struct { LONG IoErr; LONG errno; } MapTable[] =
  6215.     {
  6216.         ERROR_NO_FREE_STORE,            ENOMEM,
  6217.         ERROR_TASK_TABLE_FULL,            ENOMEM,
  6218.         ERROR_BAD_TEMPLATE,                EINVAL,
  6219.         ERROR_BAD_NUMBER,                EINVAL,
  6220.         ERROR_REQUIRED_ARG_MISSING,        EINVAL,
  6221.         ERROR_KEY_NEEDS_ARG,            EINVAL,
  6222.         ERROR_TOO_MANY_ARGS,            EINVAL,
  6223.         ERROR_UNMATCHED_QUOTES,            EINVAL,
  6224.         ERROR_LINE_TOO_LONG,            ENAMETOOLONG,
  6225.         ERROR_FILE_NOT_OBJECT,            ENOEXEC,
  6226.         ERROR_INVALID_RESIDENT_LIBRARY,    EIO,
  6227.         ERROR_NO_DEFAULT_DIR,            EIO,
  6228.         ERROR_OBJECT_IN_USE,            EBUSY,
  6229.         ERROR_OBJECT_EXISTS,            EBUSY,
  6230.         ERROR_DIR_NOT_FOUND,            ENOENT,
  6231.         ERROR_OBJECT_NOT_FOUND,            ENOENT,
  6232.         ERROR_BAD_STREAM_NAME,            EINVAL,
  6233.         ERROR_OBJECT_TOO_LARGE,            EFBIG,
  6234.         ERROR_ACTION_NOT_KNOWN,            ENOSYS,
  6235.         ERROR_INVALID_COMPONENT_NAME,    EINVAL,
  6236.         ERROR_INVALID_LOCK,                EBADF,
  6237.         ERROR_OBJECT_WRONG_TYPE,        EFTYPE,
  6238.         ERROR_DISK_NOT_VALIDATED,        EROFS,
  6239.         ERROR_DISK_WRITE_PROTECTED,        EROFS,
  6240.         ERROR_RENAME_ACROSS_DEVICES,    EXDEV,
  6241.         ERROR_DIRECTORY_NOT_EMPTY,        ENOTEMPTY,
  6242.         ERROR_TOO_MANY_LEVELS,            ENAMETOOLONG,
  6243.         ERROR_DEVICE_NOT_MOUNTED,        ENXIO,
  6244.         ERROR_SEEK_ERROR,                EIO,
  6245.         ERROR_COMMENT_TOO_BIG,            ENAMETOOLONG,
  6246.         ERROR_DISK_FULL,                ENOSPC,
  6247.         ERROR_DELETE_PROTECTED,            EACCES,
  6248.         ERROR_WRITE_PROTECTED,            EACCES,
  6249.         ERROR_READ_PROTECTED,            EACCES,
  6250.         ERROR_NOT_A_DOS_DISK,            EFTYPE,
  6251.         ERROR_NO_DISK,                    EACCES,
  6252.         ERROR_NO_MORE_ENTRIES,            EIO,
  6253.         ERROR_IS_SOFT_LINK,                EFTYPE,
  6254.         ERROR_OBJECT_LINKED,            EIO,
  6255.         ERROR_BAD_HUNK,                    ENOEXEC,
  6256.         ERROR_NOT_IMPLEMENTED,            ENOSYS,
  6257.         ERROR_RECORD_NOT_LOCKED,        EIO,
  6258.         ERROR_LOCK_COLLISION,            EACCES,
  6259.         ERROR_LOCK_TIMEOUT,                EIO,
  6260.         ERROR_UNLOCK_ERROR,                EIO,
  6261.         ERROR_BUFFER_OVERFLOW,            EIO,
  6262.         ERROR_BREAK,                    EINTR,
  6263.         ERROR_NOT_EXECUTABLE,            ENOEXEC
  6264.     };
  6265.  
  6266.     LONG ioErr = IoErr();
  6267.     int i;
  6268.  
  6269.     /* If nothing else matches, we can always
  6270.      * flag it as an I/O error.
  6271.      */
  6272.     errno = EIO;
  6273.  
  6274.     for(i = 0 ; i < NUM_ENTRIES(MapTable) ; i++)
  6275.     {
  6276.         if(MapTable[i].IoErr == ioErr)
  6277.         {
  6278.             errno = MapTable[i].errno;
  6279.             break;
  6280.         }
  6281.     }
  6282. }
  6283.  
  6284. /******************************************************************************/
  6285.  
  6286. off_t
  6287. amiga_lseek(int fd,off_t offset,int mode)
  6288. {
  6289.     struct UFB * ufb;
  6290.     off_t result = ERROR;
  6291.  
  6292.     ENTER();
  6293.     SHOWVALUE(fd);
  6294.     SHOWVALUE(offset);
  6295.     SHOWVALUE(mode);
  6296.  
  6297.     ForbidDOS();
  6298.  
  6299.     /* Make sure that we operate on a file. */
  6300.     ufb = chkufb(fd);
  6301.     if(ufb != NULL && FLAG_IS_CLEAR(ufb->ufbflg,UFB_IS_SOCKET))
  6302.         result = lseek(fd,offset,mode);
  6303.     else
  6304.         errno = EBADF;
  6305.  
  6306.     PermitDOS();
  6307.  
  6308.     RETURN(result);
  6309.     return(result);
  6310. }
  6311.  
  6312. /******************************************************************************/
  6313.  
  6314. int
  6315. amiga_chroot(char *name)    /* dummy */
  6316. {
  6317.     int result = OK;
  6318.  
  6319.     ENTER();
  6320.  
  6321.     SHOWSTRING(name);
  6322.  
  6323.     RETURN(result);
  6324.     return(result);
  6325. }
  6326.  
  6327. /******************************************************************************/
  6328.  
  6329. STATIC int
  6330. MapFileNameAmigaToUnix(
  6331.     const char *    amiga,
  6332.     char *            unix,
  6333.     int                maxUnixLen)
  6334. {
  6335.     int len,destLen;
  6336.     int result = ERROR;
  6337.  
  6338.     /* This routine makes a Unix file
  6339.      * name generated from an AmigaDOS
  6340.      * file name. This involves a slight
  6341.      * change of syntax...
  6342.      */
  6343.     D(("amiga name |%s|",amiga));
  6344.  
  6345.     len = destLen = strlen(amiga);
  6346.     if(amiga[0] == '/')
  6347.     {
  6348.         destLen = 2 + len;
  6349.     }
  6350.     else
  6351.     {
  6352.         int i;
  6353.  
  6354.         for(i = 0 ; i < len ; i++)
  6355.         {
  6356.             if(amiga[i] == ':')
  6357.             {
  6358.                 if(amiga[i+1] != '\0')
  6359.                     destLen = 1 + len;
  6360.  
  6361.                 break;
  6362.             }
  6363.         }
  6364.     }
  6365.  
  6366.     if(destLen < maxUnixLen)
  6367.     {
  6368.         if(amiga[0] == '/')
  6369.         {
  6370.             /* `/foo\0' -> `../foo\0' */
  6371.             memmove(&unix[2],amiga,len+1);
  6372.             strncpy(unix,"..",2);
  6373.         }
  6374.         else
  6375.         {
  6376.             BOOL done = FALSE;
  6377.             int i;
  6378.  
  6379.             for(i = 0 ; i < len ; i++)
  6380.             {
  6381.                 if(amiga[i] == ':')
  6382.                 {
  6383.                     if(amiga[i+1] == '\0')
  6384.                     {
  6385.                         /* `foo:\0' -> `/foo\0' */
  6386.                         memmove(&unix[1],amiga,i);
  6387.                         unix[0] = '/';
  6388.                         unix[i+1] = '\0';
  6389.                     }
  6390.                     else
  6391.                     {
  6392.                         /* `foo:bar\0' -> `/foo/bar\0' */
  6393.                         memmove(&unix[1],amiga,len+1);
  6394.                         unix[0] = '/';
  6395.                         unix[i+1] = '/';
  6396.                     }
  6397.  
  6398.                     done = TRUE;
  6399.                     break;
  6400.                 }
  6401.             }
  6402.  
  6403.             if(NOT done && unix != amiga)
  6404.                 strcpy(unix,amiga);
  6405.         }
  6406.  
  6407.         D(("unix name |%s|",unix));
  6408.  
  6409.         result = OK;
  6410.     }
  6411.     else
  6412.     {
  6413.         SHOWMSG("unix name is too long to fit");
  6414.  
  6415.         errno = ENAMETOOLONG;
  6416.     }
  6417.  
  6418.     return(result);
  6419. }
  6420.  
  6421. /******************************************************************************/
  6422.  
  6423. STATIC VOID
  6424. FlushSTDOUT(VOID)
  6425. {
  6426.     /* Flush the standard output streams so that
  6427.      * any following output will be printed after
  6428.      * any buffered stdio output.
  6429.      */
  6430.     if(WBenchMsg == NULL)
  6431.     {
  6432.         struct UFB * ufb;
  6433.  
  6434.         /* Don't let anybody stop us. */
  6435.         signal(SIGINT,SIG_IGN);
  6436.         signal(SIGTERM,SIG_IGN);
  6437.  
  6438.         ufb = chkufb(fileno(stdout));
  6439.         if(ufb != NULL && FLAG_IS_CLEAR(ufb->ufbflg,UFB_IS_SOCKET))
  6440.             fflush(stdout);
  6441.  
  6442.         ufb = chkufb(fileno(stderr));
  6443.         if(ufb != NULL && FLAG_IS_CLEAR(ufb->ufbflg,UFB_IS_SOCKET))
  6444.             fflush(stderr);
  6445.     }
  6446. }
  6447.  
  6448. VOID
  6449. _CXOVF(VOID)
  6450. {
  6451.     /* This routine is called when a stack overflow occurs. */
  6452.     FlushSTDOUT();
  6453.     ReportProblem("Stack overflow");
  6454.  
  6455.     exit(RETURN_ERROR);
  6456. }
  6457.  
  6458. VOID __regargs
  6459. _CXBRK(VOID)
  6460. {
  6461.     extern STRPTR _ProgramName;
  6462.  
  6463.     FlushSTDOUT();
  6464.  
  6465.     /* This routine is called when the program is interrupted. */
  6466.     if(DOSBase->lib_Version >= 37)
  6467.     {
  6468.         PrintFault(ERROR_BREAK,_ProgramName);
  6469.     }
  6470.     else
  6471.     {
  6472.         const char *famousLastWords = ": *** Break";
  6473.         BPTR output = Output();
  6474.  
  6475.         Write(output,(APTR)famousLastWords,strlen(famousLastWords));
  6476.         Write(output,_ProgramName,strlen(_ProgramName));
  6477.         Write(output,"\n",1);
  6478.     }
  6479.  
  6480.     exit(RETURN_WARN);
  6481. }
  6482.  
  6483. /******************************************************************************/
  6484.  
  6485. STATIC STRPTR SambaSemaphoreName = "Amiga Samba";
  6486.  
  6487. struct SambaClientNode
  6488. {
  6489.     struct MinNode    scn_MinNode;
  6490.     struct Task *    scn_Task;
  6491.     pid_t            scn_PID;
  6492. };
  6493.  
  6494. struct SambaSemaphore
  6495. {
  6496.     struct SignalSemaphore    ss_Semaphore;
  6497.     struct List                ss_ClientList;
  6498.     pid_t                    ss_PID;
  6499.     struct List                ss_FileLockList;
  6500. };
  6501.  
  6502. STATIC struct SambaSemaphore *    SambaSemaphore;
  6503. STATIC struct SambaClientNode *    ThisClient;
  6504.  
  6505. STATIC VOID
  6506. CleanupSambaSemaphore(VOID)
  6507. {
  6508.     if(ThisClient != NULL)
  6509.     {
  6510.         /* Unregister the program. */
  6511.         ObtainSemaphore((struct SignalSemaphore *)SambaSemaphore);
  6512.         Remove((struct Node *)ThisClient);
  6513.         ReleaseSemaphore((struct SignalSemaphore *)SambaSemaphore);
  6514.  
  6515.         FreeVec(ThisClient);
  6516.         ThisClient = NULL;
  6517.     }
  6518. }
  6519.  
  6520. STATIC BOOL
  6521. SetupSambaSemaphore(VOID)
  6522. {
  6523.     BOOL success = FALSE;
  6524.  
  6525.     /* We have to have the timer open to serialize the process IDs properly. */
  6526.     if(TimerBase != NULL)
  6527.     {
  6528.         Forbid();
  6529.  
  6530.         /* Try to find the global rendezvous semaphore. */
  6531.         SambaSemaphore = (struct SambaSemaphore *)FindSemaphore(SambaSemaphoreName);
  6532.         if(SambaSemaphore == NULL)
  6533.         {
  6534.             /* Couldn't find it. So, we create it... */
  6535.             SambaSemaphore = AllocMem(sizeof(*SambaSemaphore) + strlen(SambaSemaphoreName)+1,MEMF_ANY|MEMF_PUBLIC|MEMF_CLEAR);
  6536.             if(SambaSemaphore != NULL)
  6537.             {
  6538.                 /* Set up the name. */
  6539.                 SambaSemaphore->ss_Semaphore.ss_Link.ln_Name = (char *)(SambaSemaphore+1);
  6540.                 strcpy(SambaSemaphore->ss_Semaphore.ss_Link.ln_Name,SambaSemaphoreName);
  6541.  
  6542.                 /* Set the base value for all process IDs. */
  6543.                 SambaSemaphore->ss_PID = 936;
  6544.  
  6545.                 /* Clear the client list tasks are going to be registered with. */
  6546.                 NewList(&SambaSemaphore->ss_ClientList);
  6547.  
  6548.                 /* Clear the list we will use for keeping
  6549.                  * track of file segment locks.
  6550.                  */
  6551.                 NewList(&SambaSemaphore->ss_FileLockList);
  6552.  
  6553.                 AddSemaphore((struct SignalSemaphore *)SambaSemaphore);
  6554.             }
  6555.         }
  6556.  
  6557.         Permit();
  6558.     }
  6559.  
  6560.     /* If possible, register this task. */
  6561.     if(SambaSemaphore != NULL)
  6562.     {
  6563.         struct SambaClientNode * scn;
  6564.  
  6565.         scn = AllocVec(sizeof(*scn),MEMF_ANY|MEMF_PUBLIC|MEMF_CLEAR);
  6566.         if(scn != NULL)
  6567.         {
  6568.             /* That's me. */
  6569.             scn->scn_Task = FindTask(NULL);
  6570.  
  6571.             ObtainSemaphore((struct SignalSemaphore *)SambaSemaphore);
  6572.  
  6573.             /* Register this program with a new process ID. */
  6574.             scn->scn_PID = SambaSemaphore->ss_PID++;
  6575.             AddTail(&SambaSemaphore->ss_ClientList,(struct Node *)scn);
  6576.  
  6577.             ReleaseSemaphore((struct SignalSemaphore *)SambaSemaphore);
  6578.  
  6579.             ThisClient = scn;
  6580.  
  6581.             success = TRUE;
  6582.         }
  6583.     }
  6584.  
  6585.     return(success);
  6586. }
  6587.  
  6588. int
  6589. amiga_kill(pid_t pid,int sig)
  6590. {
  6591.     struct SambaClientNode * scn;
  6592.     struct Task * found = NULL;
  6593.     int result = ERROR;
  6594.  
  6595.     chkabort();
  6596.  
  6597.     ENTER();
  6598.  
  6599.     ObtainSemaphore((struct SignalSemaphore *)SambaSemaphore);
  6600.  
  6601.     /* Try to find the Samba program that responds
  6602.      * to the given process ID.
  6603.      */
  6604.     for(scn = (struct SambaClientNode *)SambaSemaphore->ss_ClientList.lh_Head ;
  6605.         scn->scn_MinNode.mln_Succ != NULL ;
  6606.         scn = (struct SambaClientNode *)scn->scn_MinNode.mln_Succ)
  6607.     {
  6608.         if(scn->scn_PID == pid)
  6609.         {
  6610.             found = scn->scn_Task;
  6611.             break;
  6612.         }
  6613.     }
  6614.  
  6615.     /* Did we find one? */
  6616.     if(found != NULL)
  6617.     {
  6618.         /* Kill the task or just do nothing? */
  6619.         if(sig == SIGTERM)
  6620.             Signal(found,SIGBREAKF_CTRL_C);
  6621.  
  6622.         result = OK;
  6623.     }
  6624.     else
  6625.     {
  6626.         errno = ESRCH;
  6627.     }
  6628.  
  6629.     ReleaseSemaphore((struct SignalSemaphore *)SambaSemaphore);
  6630.  
  6631.     RETURN(result);
  6632.     return(result);
  6633. }
  6634.  
  6635. pid_t
  6636. amiga_getpid(VOID)
  6637. {
  6638.     pid_t result;
  6639.  
  6640.     chkabort();
  6641.  
  6642.     ENTER();
  6643.  
  6644.     /* Return this program's process ID. */
  6645.     result = ThisClient->scn_PID;
  6646.  
  6647.     RETURN(result);
  6648.     return(result);
  6649. }
  6650.  
  6651. /******************************************************************************/
  6652.  
  6653. struct LockedRegionNode
  6654. {
  6655.     struct MinNode    lrn_MinNode;
  6656.     LONG            lrn_Start;
  6657.     LONG            lrn_Stop;
  6658.     pid_t            lrn_Owner;
  6659.     BOOL            lrn_Shared;
  6660. };
  6661.  
  6662. struct FileLockNode
  6663. {
  6664.     struct MinNode    fln_MinNode;
  6665.     struct List        fln_LockedRegionList;
  6666.     BPTR            fln_FileParentDir;
  6667.     UBYTE            fln_FileName[1];
  6668. };
  6669.  
  6670. STATIC VOID
  6671. RemoveLockedRegionNode(struct UFB * ufb,LONG start,LONG stop)
  6672. {
  6673.     if(FLAG_IS_SET(ufb->ufbflg,UFB_LOCKED))
  6674.     {
  6675.         BPTR fileHandle = (BPTR)ufb->ufbfh;
  6676.         struct FileLockNode * whichLock;
  6677.  
  6678.         /* Find the locked file this descriptor
  6679.          * buffer belongs to.
  6680.          */
  6681.         if(FindFileLockNodeByFileHandle(fileHandle,&whichLock) == OK && whichLock != NULL)
  6682.         {
  6683.             struct LockedRegionNode * lrn;
  6684.  
  6685.             /* Find the region to unlock and remove it. */
  6686.             for(lrn = (struct LockedRegionNode *)whichLock->fln_LockedRegionList.lh_Head ;
  6687.                 lrn->lrn_MinNode.mln_Succ != NULL ;
  6688.                 lrn = (struct LockedRegionNode *)lrn->lrn_MinNode.mln_Succ)
  6689.             {
  6690.                 if(lrn->lrn_Owner == ThisClient->scn_PID &&
  6691.                    lrn->lrn_Start == start &&
  6692.                    lrn->lrn_Stop  == stop)
  6693.                 {
  6694.                     SHOWMSG("unlocking all regions on this file");
  6695.  
  6696.                     Remove((struct Node *)lrn);
  6697.                     DeleteLockedRegionNode(lrn);
  6698.                     break;
  6699.                 }
  6700.             }
  6701.  
  6702.             /* Check if there are any locked regions left.
  6703.              * If not, mark the entire file as unlocked.
  6704.              */
  6705.             if(IsListEmpty(&whichLock->fln_LockedRegionList))
  6706.             {
  6707.                 SHOWMSG("no more regions are locked; removing the file lock node");
  6708.  
  6709.                 Remove((struct Node *)whichLock);
  6710.  
  6711.                 DeleteFileLockNode(whichLock);
  6712.  
  6713.                 CLEAR_FLAG(ufb->ufbflg,UFB_LOCKED);
  6714.             }
  6715.         }
  6716.     }
  6717. }
  6718.  
  6719. STATIC VOID
  6720. DeleteLockedRegionNode(struct LockedRegionNode * lrn)
  6721. {
  6722.     if(lrn != NULL)
  6723.         FreeMem(lrn,sizeof(*lrn));
  6724. }
  6725.  
  6726. STATIC LONG
  6727. CreateLockedRegionNode(struct LockedRegionNode ** resultPtr)
  6728. {
  6729.     struct LockedRegionNode * lrn;
  6730.     LONG error;
  6731.  
  6732.     lrn = AllocMem(sizeof(*lrn),MEMF_ANY|MEMF_PUBLIC|MEMF_CLEAR);
  6733.     if(lrn != NULL)
  6734.     {
  6735.         lrn->lrn_Owner = ThisClient->scn_PID;
  6736.  
  6737.         error = OK;
  6738.     }
  6739.     else
  6740.     {
  6741.         error = ERROR_NO_FREE_STORE;
  6742.     }
  6743.  
  6744.     (*resultPtr) = lrn;
  6745.  
  6746.     return(error);
  6747. }
  6748.  
  6749. STATIC VOID
  6750. DeleteFileLockNode(struct FileLockNode * fln)
  6751. {
  6752.     if(fln != NULL)
  6753.     {
  6754.         UnLock(fln->fln_FileParentDir);
  6755.         FreeVec(fln);
  6756.     }
  6757. }
  6758.  
  6759. STATIC LONG
  6760. CreateFileLockNode(struct UFB * ufb,struct FileLockNode ** resultPtr)
  6761. {
  6762.     struct FileLockNode * result = NULL;
  6763.     BPTR fileHandle = (BPTR)ufb->ufbfh;
  6764.     struct FileInfoBlock __aligned fib;
  6765.     LONG error = OK;
  6766.  
  6767.     /* We store a lock on the file's parent directory
  6768.      * and the name of the file for later use in
  6769.      * comparisons.
  6770.      */
  6771.     if(ExamineFH(fileHandle,&fib))
  6772.     {
  6773.         struct FileLockNode * fln;
  6774.  
  6775.         fln = AllocVec(sizeof(*fln) + strlen(fib.fib_FileName),MEMF_ANY|MEMF_PUBLIC|MEMF_CLEAR);
  6776.         if(fln != NULL)
  6777.         {
  6778.             fln->fln_FileParentDir = ParentOfFH(fileHandle);
  6779.             if(fln->fln_FileParentDir != ZERO)
  6780.             {
  6781.                 strcpy(fln->fln_FileName,fib.fib_FileName);
  6782.  
  6783.                 NewList(&fln->fln_LockedRegionList);
  6784.  
  6785.                 result = fln;
  6786.                 fln = NULL;
  6787.             }
  6788.             else
  6789.             {
  6790.                 error = IoErr();
  6791.             }
  6792.  
  6793.             DeleteFileLockNode(fln);
  6794.         }
  6795.         else
  6796.         {
  6797.             error = ERROR_NO_FREE_STORE;
  6798.         }
  6799.     }
  6800.     else
  6801.     {
  6802.         error = IoErr();
  6803.     }
  6804.  
  6805.     (*resultPtr) = result;
  6806.  
  6807.     return(error);
  6808. }
  6809.  
  6810. STATIC LONG
  6811. FindFileLockNodeByFileHandle(BPTR fileHandle,struct FileLockNode ** resultPtr)
  6812. {
  6813.     struct FileLockNode * result = NULL;
  6814.     BPTR parentDir;
  6815.     LONG error;
  6816.  
  6817.     /* Determine the file's parent directory and
  6818.      * name. These will be compared against the
  6819.      * global file lock data.
  6820.      */
  6821.     parentDir = ParentOfFH(fileHandle);
  6822.     if(parentDir != ZERO)
  6823.     {
  6824.         struct FileInfoBlock __aligned this_fib;
  6825.  
  6826.         if(ExamineFH(fileHandle,&this_fib))
  6827.         {
  6828.             struct FileLockNode * fln;
  6829.  
  6830.             #if DEBUG
  6831.             {
  6832.                 char name[MAX_FILENAME_LEN];
  6833.  
  6834.                 if(NameFromFH(fileHandle,name,sizeof(name)))
  6835.                     D(("Looking for a lock on file |%s|",name));
  6836.             }
  6837.             #endif /* DEBUG */
  6838.  
  6839.             error = OK;
  6840.  
  6841.             for(fln = (struct FileLockNode *)SambaSemaphore->ss_FileLockList.lh_Head ;
  6842.                 fln->fln_MinNode.mln_Succ != NULL ;
  6843.                 fln = (struct FileLockNode *)fln->fln_MinNode.mln_Succ)
  6844.             {
  6845.                 /* To be identical, the files must reside in the
  6846.                  * same directories and bear the same names.
  6847.                  */
  6848.                 if(SameLock(fln->fln_FileParentDir,parentDir) == LOCK_SAME)
  6849.                 {
  6850.                     if(Stricmp(fln->fln_FileName,this_fib.fib_FileName) == SAME)
  6851.                     {
  6852.                         result = fln;
  6853.                         error = OK;
  6854.  
  6855.                         break;
  6856.                     }
  6857.                 }
  6858.             }
  6859.         }
  6860.         else
  6861.         {
  6862.             error = IoErr();
  6863.         }
  6864.  
  6865.         if(result != NULL)
  6866.             SHOWMSG("found one");
  6867.         else
  6868.             SHOWMSG("didn't find one");
  6869.  
  6870.         UnLock(parentDir);
  6871.     }
  6872.     else
  6873.     {
  6874.         error = IoErr();
  6875.     }
  6876.  
  6877.     (*resultPtr) = result;
  6878.  
  6879.     return(error);
  6880. }
  6881.  
  6882. STATIC VOID
  6883. FindFileLockNodeByDrawerAndName(BPTR dirLock,STRPTR fileName,struct FileLockNode ** resultPtr)
  6884. {
  6885.     struct FileLockNode * result = NULL;
  6886.     struct FileLockNode * fln;
  6887.  
  6888.     /* This is a somewhat simplied version of FindFileLockNodeByFileHandle()
  6889.      * which works with preset drawer and name data.
  6890.      */
  6891.  
  6892.     #if DEBUG
  6893.     {
  6894.         char name[MAX_FILENAME_LEN];
  6895.  
  6896.         if(NameFromLock(dirLock,name,sizeof(name)))
  6897.         {
  6898.             if(AddPart(name,fileName,sizeof(name)))
  6899.                 D(("Looking for a lock on file |%s|",name));
  6900.         }
  6901.     }
  6902.     #endif /* DEBUG */
  6903.  
  6904.     for(fln = (struct FileLockNode *)SambaSemaphore->ss_FileLockList.lh_Head ;
  6905.         fln->fln_MinNode.mln_Succ != NULL ;
  6906.         fln = (struct FileLockNode *)fln->fln_MinNode.mln_Succ)
  6907.     {
  6908.         if(SameLock(fln->fln_FileParentDir,dirLock) == LOCK_SAME)
  6909.         {
  6910.             if(Stricmp(fln->fln_FileName,fileName) == SAME)
  6911.             {
  6912.                 result = fln;
  6913.  
  6914.                 break;
  6915.             }
  6916.         }
  6917.     }
  6918.  
  6919.     if(result != NULL)
  6920.         SHOWMSG("found one");
  6921.     else
  6922.         SHOWMSG("didn't find one");
  6923.  
  6924.     (*resultPtr) = result;
  6925. }
  6926.  
  6927. STATIC struct LockedRegionNode *
  6928. FindCollidingRegion(struct FileLockNode * fln,LONG start,LONG stop,BOOL shared)
  6929. {
  6930.     struct LockedRegionNode * result = NULL;
  6931.     struct LockedRegionNode * lrn;
  6932.  
  6933.     /* This routine looks for a locked region that overlaps
  6934.      * with the specified region. It returns a pointer to the
  6935.      * region that would collide with the specified region if
  6936.      * a new lock were to be added.
  6937.      */
  6938.     for(lrn = (struct LockedRegionNode *)fln->fln_LockedRegionList.lh_Head ;
  6939.         lrn->lrn_MinNode.mln_Succ != NULL ;
  6940.         lrn = (struct LockedRegionNode *)lrn->lrn_MinNode.mln_Succ)
  6941.     {
  6942.         /* Do the regions overlap? */
  6943.         if(lrn->lrn_Start <= stop && start <= lrn->lrn_Stop)
  6944.         {
  6945.             /* Two shared regions may always overlap.
  6946.              * How about the rest?
  6947.              */
  6948.             if(NOT shared || NOT lrn->lrn_Shared)
  6949.             {
  6950.                 /* The lock owner may add as many exclusive
  6951.                  * or shared locks to the same region as
  6952.                  * necessary.
  6953.                  */
  6954.                 if(lrn->lrn_Owner == ThisClient->scn_PID)
  6955.                     continue;
  6956.  
  6957.                 /* So we found a region that would
  6958.                  * cause a collision.
  6959.                  */
  6960.                 result = lrn;
  6961.                 break;
  6962.             }
  6963.         }
  6964.     }
  6965.  
  6966.     return(result);
  6967. }
  6968.  
  6969. STATIC VOID
  6970. CleanupFileLocks(int fd)
  6971. {
  6972.     struct UFB * ufb;
  6973.  
  6974.     /* This routine removes all locked regions from a file
  6975.      * before it is eventually closed.
  6976.      */
  6977.  
  6978.     ufb = chkufb(fd);
  6979.     if(ufb != NULL && FLAG_IS_SET(ufb->ufbflg,UFB_LOCKED))
  6980.     {
  6981.         BPTR fileHandle = (BPTR)ufb->ufbfh;
  6982.         struct FileLockNode * whichLock;
  6983.  
  6984.         ObtainSemaphore((struct SignalSemaphore *)SambaSemaphore);
  6985.  
  6986.         if(FindFileLockNodeByFileHandle(fileHandle,&whichLock) == OK && whichLock != NULL)
  6987.         {
  6988.             struct LockedRegionNode * lrn_this;
  6989.             struct LockedRegionNode * lrn_next;
  6990.  
  6991.             SHOWMSG("unlocking all regions on this file");
  6992.  
  6993.             for(lrn_this = (struct LockedRegionNode *)whichLock->fln_LockedRegionList.lh_Head ;
  6994.                (lrn_next = (struct LockedRegionNode *)lrn_this->lrn_MinNode.mln_Succ) != NULL ;
  6995.                 lrn_this = lrn_next)
  6996.             {
  6997.                 if(lrn_this->lrn_Owner == ThisClient->scn_PID)
  6998.                 {
  6999.                     Remove((struct Node *)lrn_this);
  7000.                     DeleteLockedRegionNode(lrn_this);
  7001.                 }
  7002.             }
  7003.  
  7004.             if(IsListEmpty(&whichLock->fln_LockedRegionList))
  7005.             {
  7006.                 SHOWMSG("no more regions are locked; removing the file lock node");
  7007.  
  7008.                 Remove((struct Node *)whichLock);
  7009.  
  7010.                 DeleteFileLockNode(whichLock);
  7011.             }
  7012.         }
  7013.  
  7014.         CLEAR_FLAG(ufb->ufbflg,UFB_LOCKED);
  7015.  
  7016.         ReleaseSemaphore((struct SignalSemaphore *)SambaSemaphore);
  7017.     }
  7018. }
  7019.  
  7020. #define SEEK_ERROR (-1)
  7021.  
  7022. STATIC int
  7023. HandleFileLocking(int cmd,struct flock * l,struct UFB * ufb)
  7024. {
  7025.     int result = ERROR;
  7026.  
  7027.     /* This routine implements advisory file segment locking
  7028.      * similar to 4.4BSD, but not quite the same. The functionality
  7029.      * is a subset, somewhat similar to the functionality offered
  7030.      * by the AmigaDOS LockRecord() and UnlockRecord() functions.
  7031.      * This means for example that every unlock request must
  7032.      * match the size and position of the corresponding locking
  7033.      * request.
  7034.      *
  7035.      * This implementation was chosen because not every Amiga
  7036.      * filing system implements record locking and Samba
  7037.      * absolutely requires this functionality to work.
  7038.      */
  7039.     if(l != NULL && ufb != NULL)
  7040.     {
  7041.         /* Can we make sense of the input parameters? */
  7042.         if(F_RDLCK <= l->l_type && l->l_type <= F_WRLCK &&
  7043.           (l->l_whence == SEEK_SET || l->l_whence == SEEK_CUR || l->l_whence == SEEK_END))
  7044.         {
  7045.             struct LockedRegionNode * lrn = NULL;
  7046.             struct FileLockNode * fln = NULL;
  7047.             LONG error;
  7048.  
  7049.             if((cmd == F_SETLK || cmd == F_SETLKW) && (l->l_type != F_UNLCK))
  7050.             {
  7051.                 SHOWMSG("this is a lock request");
  7052.                 error = CreateFileLockNode(ufb,&fln);
  7053.                 if(error == OK)
  7054.                     error = CreateLockedRegionNode(&lrn);
  7055.             }
  7056.             else
  7057.             {
  7058.                 SHOWMSG("this is not a lock request");
  7059.                 error = OK;
  7060.             }
  7061.  
  7062.             if(error == OK)
  7063.             {
  7064.                 struct FileInfoBlock __aligned fib;
  7065.                 BPTR fileHandle = (BPTR)ufb->ufbfh;
  7066.                 BOOL dataIsValid = TRUE;
  7067.                 LONG currentPosition;
  7068.                 LONG start = 0;
  7069.                 LONG len = 0;
  7070.  
  7071.                 /* Now calculate the position of the
  7072.                  * first byte to lock and the number
  7073.                  * of bytes to lock.
  7074.                  */
  7075.                 switch(l->l_whence)
  7076.                 {
  7077.                     case SEEK_SET:
  7078.  
  7079.                         start = l->l_start;
  7080.  
  7081.                         if(l->l_len == 0)
  7082.                         {
  7083.                             if(ExamineFH(fileHandle,&fib))
  7084.                                 len = fib.fib_Size - start;
  7085.                             else
  7086.                                 dataIsValid = FALSE;
  7087.                         }
  7088.                         else
  7089.                         {
  7090.                             len = l->l_len;
  7091.                         }
  7092.  
  7093.                         break;
  7094.  
  7095.                     case SEEK_CUR:
  7096.  
  7097.                         currentPosition = Seek(fileHandle,0,OFFSET_CURRENT);
  7098.                         if(currentPosition != SEEK_ERROR)
  7099.                         {
  7100.                             start = currentPosition + l->l_start;
  7101.  
  7102.                             if(l->l_len == 0)
  7103.                             {
  7104.                                 if(ExamineFH(fileHandle,&fib))
  7105.                                     len = fib.fib_Size - start;
  7106.                                 else
  7107.                                     dataIsValid = FALSE;
  7108.                             }
  7109.                             else
  7110.                             {
  7111.                                 len = l->l_len;
  7112.                             }
  7113.                         }
  7114.                         else
  7115.                         {
  7116.                             dataIsValid = FALSE;
  7117.                         }
  7118.  
  7119.                         break;
  7120.  
  7121.                     case SEEK_END:
  7122.                     default:
  7123.  
  7124.                         if(ExamineFH(fileHandle,&fib))
  7125.                         {
  7126.                             start = fib.fib_Size + l->l_start;
  7127.  
  7128.                             if(l->l_len == 0)
  7129.                                 len = fib.fib_Size - start;
  7130.                             else
  7131.                                 len = l->l_len;
  7132.                         }
  7133.                         else
  7134.                         {
  7135.                             dataIsValid = FALSE;
  7136.                         }
  7137.  
  7138.                         break;
  7139.                 }
  7140.  
  7141.                 SHOWVALUE(start);
  7142.                 SHOWVALUE(len);
  7143.  
  7144.                 /* Did we get everything we needed? */
  7145.                 if(dataIsValid)
  7146.                 {
  7147.                     if(start >= 0 && len >= 0)
  7148.                     {
  7149.                         if(len > 0)
  7150.                         {
  7151.                             if(l->l_type == F_UNLCK)
  7152.                             {
  7153.                                 D(("unlocking %ld..%ld",start,start+len-1));
  7154.  
  7155.                                 ObtainSemaphore((struct SignalSemaphore *)SambaSemaphore);
  7156.  
  7157.                                 RemoveLockedRegionNode(ufb,start,start+len-1);
  7158.  
  7159.                                 ReleaseSemaphore((struct SignalSemaphore *)SambaSemaphore);
  7160.  
  7161.                                 result = OK;
  7162.                             }
  7163.                             else if(cmd == F_SETLKW)
  7164.                             {
  7165.                                 BPTR parentDir;
  7166.  
  7167.                                 D(("  locking %ld..%ld",start,start+len-1));
  7168.  
  7169.                                 parentDir = ParentOfFH(fileHandle);
  7170.                                 if(parentDir != ZERO)
  7171.                                 {
  7172.                                     struct FileInfoBlock __aligned fib;
  7173.  
  7174.                                     if(ExamineFH(fileHandle,&fib))
  7175.                                     {
  7176.                                         BOOL shared = (BOOL)(l->l_type == F_RDLCK);
  7177.                                         struct FileLockNode * existing_fln;
  7178.                                         BOOL stopped = FALSE;
  7179.                                         BOOL locked;
  7180.  
  7181.                                         if(shared)
  7182.                                             D(("this is a shared lock; waiting for completion"));
  7183.                                         else
  7184.                                             D(("this is an exclusive lock; waiting for completion"));
  7185.  
  7186.                                         lrn->lrn_Start    = start;
  7187.                                         lrn->lrn_Stop    = start+len-1;
  7188.                                         lrn->lrn_Shared    = shared;
  7189.  
  7190.                                         /* Retry until we manage to lock the record. */
  7191.                                         locked = FALSE;
  7192.                                         do
  7193.                                         {
  7194.                                             ObtainSemaphore((struct SignalSemaphore *)SambaSemaphore);
  7195.  
  7196.                                             FindFileLockNodeByDrawerAndName(parentDir,fib.fib_FileName,&existing_fln);
  7197.                                             if(existing_fln != NULL)
  7198.                                             {
  7199.                                                 SHOWMSG("that file is already locked by someone");
  7200.  
  7201.                                                 if(FindCollidingRegion(existing_fln,start,start+len-1,shared) == NULL)
  7202.                                                 {
  7203.                                                     SHOWMSG("but the locks don't collide");
  7204.  
  7205.                                                     AddTail(&existing_fln->fln_LockedRegionList,(struct Node *)lrn);
  7206.                                                     lrn = NULL;
  7207.  
  7208.                                                     locked = TRUE;
  7209.                                                 }
  7210.                                                 else
  7211.                                                 {
  7212.                                                     SHOWMSG("and the locks collide");
  7213.                                                 }
  7214.                                             }
  7215.                                             else
  7216.                                             {
  7217.                                                 SHOWMSG("nobody has any locks on this file");
  7218.  
  7219.                                                 AddTail(&SambaSemaphore->ss_FileLockList,(struct Node *)fln);
  7220.                                                 AddTail(&fln->fln_LockedRegionList,(struct Node *)lrn);
  7221.  
  7222.                                                 fln = NULL;
  7223.                                                 lrn = NULL;
  7224.  
  7225.                                                 locked = TRUE;
  7226.                                             }
  7227.  
  7228.                                             ReleaseSemaphore((struct SignalSemaphore *)SambaSemaphore);
  7229.  
  7230.                                             if(NOT locked)
  7231.                                             {
  7232.                                                 const int randMax = RAND_MAX / 65536;
  7233.                                                 LONG numRandomTicks;
  7234.  
  7235.                                                 if(CheckAbort())
  7236.                                                 {
  7237.                                                     stopped = TRUE;
  7238.                                                     break;
  7239.                                                 }
  7240.  
  7241.                                                 /* Wait a little before retrying
  7242.                                                  * the locking operation. We add
  7243.                                                  * a little randomness here to
  7244.                                                  * reduce the likelihood of two
  7245.                                                  * competing processes trying to
  7246.                                                  * lock the same file at the
  7247.                                                  * same time.
  7248.                                                  */
  7249.  
  7250.                                                 numRandomTicks = ((TICKS_PER_SECOND / 2) * (rand() / 65536)) / randMax;
  7251.  
  7252.                                                 if(numRandomTicks > 0)
  7253.                                                     Delay(numRandomTicks);
  7254.                                             }
  7255.                                         }
  7256.                                         while(NOT locked);
  7257.  
  7258.                                         if(stopped)
  7259.                                         {
  7260.                                             SHOWMSG("lock polling loop stopped");
  7261.  
  7262.                                             DeleteFileLockNode(fln);
  7263.                                             fln = NULL;
  7264.  
  7265.                                             DeleteLockedRegionNode(lrn);
  7266.                                             lrn = NULL;
  7267.  
  7268.                                             UnLock(parentDir);
  7269.                                             parentDir = ZERO;
  7270.  
  7271.                                             errno = EINTR;
  7272.  
  7273.                                             raise(SIGINT);
  7274.                                         }
  7275.  
  7276.                                         if(locked)
  7277.                                         {
  7278.                                             SHOWMSG("the file now has a lock set");
  7279.                                             SET_FLAG(ufb->ufbflg,UFB_LOCKED);
  7280.                                             result = OK;
  7281.                                         }
  7282.                                     }
  7283.                                     else
  7284.                                     {
  7285.                                         SHOWMSG("couldn't read this file's name");
  7286.                                         MapIoErrToErrno();
  7287.                                     }
  7288.  
  7289.                                     UnLock(parentDir);
  7290.                                 }
  7291.                                 else
  7292.                                 {
  7293.                                     SHOWMSG("couldn't get a lock on the file's parent directory");
  7294.                                     MapIoErrToErrno();
  7295.                                 }
  7296.                             }
  7297.                             else if(cmd == F_SETLK)
  7298.                             {
  7299.                                 BOOL shared = (BOOL)(l->l_type == F_RDLCK);
  7300.                                 struct FileLockNode * existing_fln;
  7301.                                 BOOL locked = FALSE;
  7302.  
  7303.                                 if(shared)
  7304.                                     D(("this is a shared lock"));
  7305.                                 else
  7306.                                     D(("this is an exclusive lock"));
  7307.  
  7308.                                 lrn->lrn_Start    = start;
  7309.                                 lrn->lrn_Stop    = start+len-1;
  7310.                                 lrn->lrn_Shared    = shared;
  7311.  
  7312.                                 ObtainSemaphore((struct SignalSemaphore *)SambaSemaphore);
  7313.  
  7314.                                 if(FindFileLockNodeByFileHandle(fileHandle,&existing_fln) == OK)
  7315.                                 {
  7316.                                     if(existing_fln != NULL)
  7317.                                     {
  7318.                                         SHOWMSG("that file is already locked by someone else");
  7319.  
  7320.                                         if(FindCollidingRegion(existing_fln,start,start+len-1,shared) == NULL)
  7321.                                         {
  7322.                                             SHOWMSG("but the locks don't collide");
  7323.  
  7324.                                             AddTail(&existing_fln->fln_LockedRegionList,(struct Node *)lrn);
  7325.                                             lrn = NULL;
  7326.  
  7327.                                             locked = TRUE;
  7328.                                         }
  7329.                                         else
  7330.                                         {
  7331.                                             SHOWMSG("and the locks collide");
  7332.                                         }
  7333.                                     }
  7334.                                     else
  7335.                                     {
  7336.                                         SHOWMSG("nobody has any locks on this file");
  7337.  
  7338.                                         AddTail(&SambaSemaphore->ss_FileLockList,(struct Node *)fln);
  7339.                                         AddTail(&fln->fln_LockedRegionList,(struct Node *)lrn);
  7340.  
  7341.                                         fln = NULL;
  7342.                                         lrn = NULL;
  7343.  
  7344.                                         locked = TRUE;
  7345.                                     }
  7346.                                 }
  7347.  
  7348.                                 ReleaseSemaphore((struct SignalSemaphore *)SambaSemaphore);
  7349.  
  7350.                                 if(locked)
  7351.                                 {
  7352.                                     SHOWMSG("the file now has a lock set");
  7353.  
  7354.                                     SET_FLAG(ufb->ufbflg,UFB_LOCKED);
  7355.  
  7356.                                     result = OK;
  7357.                                 }
  7358.                                 else
  7359.                                 {
  7360.                                     errno = EACCES;
  7361.                                 }
  7362.                             }
  7363.                             else if (cmd == F_GETLK)
  7364.                             {
  7365.                                 struct FileLockNode * fln;
  7366.                                 LONG error;
  7367.  
  7368.                                 SafeObtainSemaphoreShared((struct SignalSemaphore *)SambaSemaphore);
  7369.  
  7370.                                 SHOWMSG("checking for possible lock collision");
  7371.  
  7372.                                 error = FindFileLockNodeByFileHandle(fileHandle,&fln);
  7373.                                 if(error == OK)
  7374.                                 {
  7375.                                     if(fln != NULL)
  7376.                                     {
  7377.                                         struct LockedRegionNode * lrn;
  7378.                                         BOOL shared;
  7379.  
  7380.                                         SHOWMSG("somebody has locked this file");
  7381.  
  7382.                                         shared = (BOOL)(l->l_type == F_RDLCK);
  7383.  
  7384.                                         lrn = FindCollidingRegion(fln,start,start+len-1,shared);
  7385.                                         if(lrn != NULL)
  7386.                                         {
  7387.                                             SHOWMSG("there is a possible lock collision");
  7388.  
  7389.                                             l->l_type    = (lrn->lrn_Shared ? F_RDLCK : F_WRLCK);
  7390.                                             l->l_whence    = SEEK_SET;
  7391.                                             l->l_start    = lrn->lrn_Start;
  7392.                                             l->l_len    = lrn->lrn_Stop - lrn->lrn_Start + 1;
  7393.                                             l->l_pid    = lrn->lrn_Owner;
  7394.                                         }
  7395.                                         else
  7396.                                         {
  7397.                                             SHOWMSG("there is no lock collision");
  7398.  
  7399.                                             l->l_type = F_UNLCK;
  7400.                                         }
  7401.                                     }
  7402.                                     else
  7403.                                     {
  7404.                                         SHOWMSG("nobody has locked this file");
  7405.  
  7406.                                         l->l_type = F_UNLCK;
  7407.                                     }
  7408.  
  7409.                                     result = OK;
  7410.                                 }
  7411.                                 else
  7412.                                 {
  7413.                                     SetIoErr(error);
  7414.  
  7415.                                     MapIoErrToErrno();
  7416.                                 }
  7417.  
  7418.                                 ReleaseSemaphore((struct SignalSemaphore *)SambaSemaphore);
  7419.                             }
  7420.                         }
  7421.                         else
  7422.                         {
  7423.                             SHOWMSG("zero length lock/unlock");
  7424.                             result = OK;
  7425.                         }
  7426.                     }
  7427.                     else
  7428.                     {
  7429.                         SHOWMSG("invalid start/len");
  7430.                         SHOWVALUE(start);
  7431.                         SHOWVALUE(len);
  7432.                         errno = EINVAL;
  7433.                     }
  7434.                 }
  7435.                 else
  7436.                 {
  7437.                     SHOWMSG("couldn't determine start/len");
  7438.                     MapIoErrToErrno();
  7439.                 }
  7440.             }
  7441.             else
  7442.             {
  7443.                 SHOWMSG("couldn't get the bookkeeping memory needed");
  7444.                 MapIoErrToErrno();
  7445.             }
  7446.  
  7447.             DeleteFileLockNode(fln);
  7448.             DeleteLockedRegionNode(lrn);
  7449.         }
  7450.         else
  7451.         {
  7452.             SHOWMSG("invalid lock type or seek offset");
  7453.             SHOWVALUE(l->l_type);
  7454.             SHOWVALUE(l->l_whence);
  7455.             errno = EINVAL;
  7456.         }
  7457.     }
  7458.     else
  7459.     {
  7460.         SHOWMSG("no flock or no ufb");
  7461.         SHOWVALUE(l);
  7462.         SHOWVALUE(ufb);
  7463.  
  7464.         errno = EINVAL;
  7465.     }
  7466.  
  7467.     RETURN(result);
  7468.     return(result);
  7469. }
  7470.  
  7471. int
  7472. amiga_fcntl(int fd,int cmd,unsigned long arg)
  7473. {
  7474.     struct UFB * ufb;
  7475.     struct flock * l;
  7476.     int result = ERROR;
  7477.  
  7478.     chkabort();
  7479.  
  7480.     ENTER();
  7481.  
  7482.     /* Don't try to lock data in a socket... */
  7483.     ufb = chkufb(fd);
  7484.     if(ufb == NULL || FLAG_IS_SET(ufb->ufbflg,UFB_IS_SOCKET))
  7485.         ufb = NULL;
  7486.  
  7487.     l = (struct flock *)arg;
  7488.  
  7489.     switch(cmd)
  7490.     {
  7491.         /* Get the first lock that blocks the lock description pointed to
  7492.          * by the third argument, arg, taken as a pointer to a struct
  7493.          * flock (see above).  The information retrieved overwrites the
  7494.          * information passed to fcntl in the flock structure.  If no
  7495.          * lock is found that would prevent this lock from being created,
  7496.          * the structure is left unchanged by this function call except
  7497.          * for the lock type which is set to F_UNLCK.
  7498.          */
  7499.         case F_GETLK:
  7500.  
  7501.             SHOWMSG("F_GETLK");
  7502.             result = HandleFileLocking(cmd,l,ufb);
  7503.             break;
  7504.  
  7505.         /* Set or clear a file segment lock according to the lock de-
  7506.          * scription pointed to by the third argument, arg, taken as a
  7507.          * pointer to a struct flock (see above).    F_SETLK is used to es-
  7508.          * tablish shared (or read) locks (F_RDLCK) or exclusive (or
  7509.          * write) locks, (F_WRLCK), as well as remove either type of lock
  7510.          * (F_UNLCK). If a shared or exclusive lock cannot be set, fcntl
  7511.          * returns immediately with EACCES.
  7512.          */
  7513.         case F_SETLK:
  7514.  
  7515.             SHOWMSG("F_SETLK");
  7516.             result = HandleFileLocking(cmd,l,ufb);
  7517.             break;
  7518.  
  7519.         /* This command is the same as F_SETLK except that if a shared or
  7520.          * exclusive lock is blocked by other locks, the process waits
  7521.          * until the request can be satisfied.  If a signal that is to be
  7522.          * caught is received while fcntl is waiting for a region, the
  7523.          * fcntl will be interrupted if the signal handler has not speci-
  7524.          * fied the SA_RESTART (see sigaction(2)).
  7525.          */
  7526.         case F_SETLKW:
  7527.  
  7528.             SHOWMSG("F_SETLKW");
  7529.             result = HandleFileLocking(cmd,l,ufb);
  7530.             break;
  7531.  
  7532.         /* Get descriptor status flags, as described below (arg is ig-
  7533.          * noted).
  7534.          */
  7535.         case F_GETFL:
  7536.  
  7537.             SHOWMSG("F_GETFL");
  7538.             result = IsDescriptorNonblocking(fd) ? O_NONBLOCK : 0;
  7539.             break;
  7540.  
  7541.         /* Set descriptor status flags to arg. */
  7542.         case F_SETFL:
  7543.  
  7544.             SHOWMSG("F_SETFL");
  7545.             if(FLAG_IS_SET(arg,O_NONBLOCK))
  7546.                 BlockDescriptor(fd);
  7547.             else
  7548.                 UnblockDescriptor(fd);
  7549.  
  7550.             result = OK;
  7551.             break;
  7552.  
  7553.         default:
  7554.  
  7555.             D(("Unknown command %ld",cmd));
  7556.             errno = ENOSYS;
  7557.             break;
  7558.     }
  7559.  
  7560.     RETURN(result);
  7561.     return(result);
  7562. }
  7563.  
  7564. /******************************************************************************/
  7565.  
  7566. int
  7567. amiga_fgetc(FILE *in)
  7568. {
  7569.     struct UFB * ufb;
  7570.     int result = ERROR;
  7571.  
  7572.     PUSH_ASSERTS();
  7573.  
  7574.     chkabort();
  7575.  
  7576.     ufb = chkufb(fileno(in));
  7577.     if(ufb != NULL && FLAG_IS_SET(ufb->ufbflg,UFB_IS_SOCKET))
  7578.     {
  7579.         UBYTE c;
  7580.  
  7581.         ENTER();
  7582.         SHOWMSG("input from socket");
  7583.  
  7584.         if(recv(ufb->ufbfh,&c,1,0) == 1)
  7585.             result = c;
  7586.     }
  7587.     else
  7588.     {
  7589.         result = fgetc(in);
  7590.     }
  7591.  
  7592.     RETURN(result);
  7593.     POP();
  7594.     return(result);
  7595. }
  7596.  
  7597. char *
  7598. amiga_fgets(char *str,int n,FILE * in)
  7599. {
  7600.     struct UFB * ufb;
  7601.     char *result;
  7602.  
  7603.     ENTER();
  7604.  
  7605.     ufb = chkufb(fileno(in));
  7606.     if(ufb != NULL && FLAG_IS_SET(ufb->ufbflg,UFB_IS_SOCKET))
  7607.     {
  7608.         char *s = str;
  7609.         LONG rc;
  7610.         UBYTE c;
  7611.  
  7612.         SHOWMSG("input from socket");
  7613.         result = str;
  7614.  
  7615.         while(--n > 0)
  7616.         {
  7617.             chkabort();
  7618.  
  7619.             rc = recv(ufb->ufbfh,&c,1,0);
  7620.             if(rc == 1)
  7621.             {
  7622.                 (*str++) = c;
  7623.  
  7624.                 if(c == '\n')
  7625.                     break;
  7626.             }
  7627.             else
  7628.             {
  7629.                 /* End of stream or nothing read? */
  7630.                 if(rc < 0 || str == s)
  7631.                     result = NULL;
  7632.  
  7633.                 break;
  7634.             }
  7635.         }
  7636.  
  7637.         if(result != NULL)
  7638.             (*str) = '\0';
  7639.     }
  7640.     else
  7641.     {
  7642.         result = fgets(str,n,in);
  7643.     }
  7644.  
  7645.     RETURN(result);
  7646.     return(result);
  7647. }
  7648.  
  7649. int
  7650. amiga_fputs(const char *str,FILE *out)
  7651. {
  7652.     struct UFB * ufb;
  7653.     int result;
  7654.  
  7655.     chkabort();
  7656.  
  7657.     ENTER();
  7658.  
  7659.     ufb = chkufb(fileno(out));
  7660.     if(ufb != NULL && FLAG_IS_SET(ufb->ufbflg,UFB_IS_SOCKET))
  7661.     {
  7662.         SHOWMSG("output to socket");
  7663.  
  7664.         if(NOT STRING_IS_EMPTY(str))
  7665.             result = send(ufb->ufbfh,str,strlen(str),0);
  7666.         else
  7667.             result = OK;
  7668.  
  7669.         if(result == OK)
  7670.             result = send(ufb->ufbfh,"\n",1,0);
  7671.     }
  7672.     else
  7673.     {
  7674.         result = fputs(str,out);
  7675.     }
  7676.  
  7677.     RETURN(result);
  7678.     return(result);
  7679. }
  7680.  
  7681. int
  7682. amiga_puts(const char *str)
  7683. {
  7684.     int result;
  7685.  
  7686.     result = amiga_fputs(str,stdout);
  7687.  
  7688.     return(result);
  7689. }
  7690.  
  7691. int
  7692. amiga_vfprintf(FILE *out,const char *fmt,va_list args)
  7693. {
  7694.     struct UFB * ufb;
  7695.     int result;
  7696.  
  7697.     chkabort();
  7698.  
  7699.     ENTER();
  7700.  
  7701.     ufb = chkufb(fileno(out));
  7702.     if(ufb != NULL && FLAG_IS_SET(ufb->ufbflg,UFB_IS_SOCKET))
  7703.     {
  7704.         char buffer[1024];
  7705.  
  7706.         SHOWMSG("output to socket");
  7707.  
  7708.         vsnprintf(buffer,sizeof(buffer)-1,fmt,args);
  7709.         buffer[sizeof(buffer)-1] = '\0';
  7710.  
  7711.         if(NOT STRING_IS_EMPTY(buffer))
  7712.             result = send(ufb->ufbfh,buffer,strlen(buffer),0);
  7713.         else
  7714.             result = 0;
  7715.     }
  7716.     else
  7717.     {
  7718.         result = vfprintf(out,fmt,args);
  7719.     }
  7720.  
  7721.     RETURN(result);
  7722.     return(result);
  7723. }
  7724.  
  7725. int
  7726. amiga_fprintf(FILE *out,const char *fmt,...)
  7727. {
  7728.     va_list args;
  7729.     int result;
  7730.  
  7731.     va_start(args,fmt);
  7732.     result = amiga_vfprintf(out,fmt,args);
  7733.     va_end(args);
  7734.  
  7735.     return(result);
  7736. }
  7737.  
  7738. int
  7739. amiga_printf(const char *fmt,...)
  7740. {
  7741.     va_list args;
  7742.     int result;
  7743.  
  7744.     va_start(args,fmt);
  7745.     result = amiga_vfprintf(stdout,fmt,args);
  7746.     va_end(args);
  7747.  
  7748.     return(result);
  7749. }
  7750.  
  7751. size_t
  7752. amiga_fwrite(const void *data,size_t blockSize,size_t numBlocks,FILE *out)
  7753. {
  7754.     struct UFB * ufb;
  7755.     size_t result;
  7756.  
  7757.     chkabort();
  7758.  
  7759.     ENTER();
  7760.  
  7761.     ufb = chkufb(fileno(out));
  7762.     if(ufb != NULL && FLAG_IS_SET(ufb->ufbflg,UFB_IS_SOCKET))
  7763.     {
  7764.         SHOWMSG("output to socket");
  7765.  
  7766.         result = send(ufb->ufbfh,(APTR)data,blockSize * numBlocks,0);
  7767.         if(result > 0)
  7768.             result = (result/blockSize);
  7769.     }
  7770.     else
  7771.     {
  7772.         result = fwrite(data,blockSize,numBlocks,out);
  7773.     }
  7774.  
  7775.     RETURN(result);
  7776.     return(result);
  7777. }
  7778.  
  7779. size_t
  7780. amiga_fread(void *data,size_t blockSize,size_t numBlocks,FILE *in)
  7781. {
  7782.     struct UFB * ufb;
  7783.     size_t result;
  7784.  
  7785.     chkabort();
  7786.  
  7787.     ENTER();
  7788.  
  7789.     ufb = chkufb(fileno(in));
  7790.     if(ufb != NULL && FLAG_IS_SET(ufb->ufbflg,UFB_IS_SOCKET))
  7791.     {
  7792.         SHOWMSG("input from socket");
  7793.  
  7794.         result = recv(ufb->ufbfh,(APTR)data,blockSize * numBlocks,0);
  7795.         if(result > 0)
  7796.             result = (result/blockSize);
  7797.     }
  7798.     else
  7799.     {
  7800.         result = fread(data,blockSize,numBlocks,in);
  7801.     }
  7802.  
  7803.     RETURN(result);
  7804.     return(result);
  7805. }
  7806.  
  7807. int
  7808. amiga_fclose(FILE * stream)
  7809. {
  7810.     struct UFB * ufb;
  7811.     int result;
  7812.  
  7813.     chkabort();
  7814.  
  7815.     ENTER();
  7816.  
  7817.     ufb = chkufb(fileno(stream));
  7818.     if(ufb != NULL && FLAG_IS_SET(ufb->ufbflg,UFB_IS_SOCKET))
  7819.         result = OK;
  7820.     else
  7821.         result = fclose(stream);
  7822.  
  7823.     RETURN(result);
  7824.     return(result);
  7825. }
  7826.  
  7827. int
  7828. amiga_fflush(FILE * stream)
  7829. {
  7830.     struct UFB * ufb;
  7831.     int result;
  7832.  
  7833.     chkabort();
  7834.  
  7835.     ENTER();
  7836.  
  7837.     ufb = chkufb(fileno(stream));
  7838.     if(ufb != NULL && FLAG_IS_SET(ufb->ufbflg,UFB_IS_SOCKET))
  7839.         result = OK;
  7840.     else
  7841.         result = fflush(stream);
  7842.  
  7843.     RETURN(result);
  7844.     return(result);
  7845. }
  7846.  
  7847. int
  7848. amiga_fseek(FILE * stream,long int offset,int mode)
  7849. {
  7850.     struct UFB * ufb;
  7851.     int result;
  7852.  
  7853.     chkabort();
  7854.  
  7855.     ENTER();
  7856.  
  7857.     ufb = chkufb(fileno(stream));
  7858.     if(ufb != NULL && FLAG_IS_SET(ufb->ufbflg,UFB_IS_SOCKET))
  7859.         result = OK;
  7860.     else
  7861.         result = fseek(stream,offset,mode);
  7862.  
  7863.     RETURN(result);
  7864.     return(result);
  7865. }
  7866.  
  7867. long int
  7868. amiga_ftell(FILE * stream)
  7869. {
  7870.     struct UFB * ufb;
  7871.     long int result;
  7872.  
  7873.     chkabort();
  7874.  
  7875.     ENTER();
  7876.  
  7877.     ufb = chkufb(fileno(stream));
  7878.     if(ufb != NULL && FLAG_IS_SET(ufb->ufbflg,UFB_IS_SOCKET))
  7879.         result = 0;
  7880.     else
  7881.         result = ftell(stream);
  7882.  
  7883.     RETURN(result);
  7884.     return(result);
  7885. }
  7886.  
  7887. /******************************************************************************/
  7888.  
  7889. int
  7890. amiga_setvbuf(FILE *stream,char *buff,int type,size_t size)
  7891. {
  7892.     struct UFB * ufb;
  7893.     int result;
  7894.  
  7895.     chkabort();
  7896.  
  7897.     ENTER();
  7898.  
  7899.     ufb = chkufb(fileno(stream));
  7900.     if(ufb != NULL && FLAG_IS_SET(ufb->ufbflg,UFB_IS_SOCKET))
  7901.         result = OK;
  7902.     else
  7903.         result = setvbuf(stream,buff,type,size);
  7904.  
  7905.     RETURN(result);
  7906.     return(result);
  7907. }
  7908.  
  7909. /******************************************************************************/
  7910.  
  7911. int
  7912. amiga_fputc(int c,FILE *stream)
  7913. {
  7914.     struct UFB * ufb;
  7915.     int result = ERROR;
  7916.  
  7917.     chkabort();
  7918.  
  7919.     ENTER();
  7920.  
  7921.     ufb = chkufb(fileno(stream));
  7922.     if(ufb != NULL && FLAG_IS_SET(ufb->ufbflg,UFB_IS_SOCKET))
  7923.     {
  7924.         UBYTE oneByte = c;
  7925.  
  7926.         if(send(ufb->ufbfh,&oneByte,1,0) > 0)
  7927.             result = OK;
  7928.     }
  7929.     else
  7930.     {
  7931.         result = fputc(c,stream);
  7932.     }
  7933.  
  7934.     RETURN(result);
  7935.     return(result);
  7936. }
  7937.  
  7938. /******************************************************************************/
  7939.  
  7940. VOID
  7941. amiga_setbuf(FILE *stream,char *buffer)
  7942. {
  7943.     struct UFB * ufb;
  7944.  
  7945.     chkabort();
  7946.  
  7947.     ENTER();
  7948.  
  7949.     ufb = chkufb(fileno(stream));
  7950.     if(ufb != NULL && FLAG_IS_SET(ufb->ufbflg,UFB_IS_SOCKET))
  7951.     {
  7952.         /* Do nothing */
  7953.     }
  7954.     else
  7955.     {
  7956.         setbuf(stream,buffer);
  7957.     }
  7958.  
  7959.     LEAVE();
  7960. }
  7961.  
  7962. /******************************************************************************/
  7963.  
  7964. int
  7965. amiga_recv(int fd,void *buff,size_t nbytes,int flags)
  7966. {
  7967.     struct UFB * ufb;
  7968.     int result = ERROR;
  7969.  
  7970.     ENTER();
  7971.  
  7972.     ufb = chkufb(fd);
  7973.     if(ufb != NULL && FLAG_IS_SET(ufb->ufbflg,UFB_IS_SOCKET))
  7974.         result = recv(ufb->ufbfh,buff,nbytes,flags);
  7975.     else
  7976.         errno = EBADF;
  7977.  
  7978.     RETURN(result);
  7979.     return(result);
  7980. }
  7981.  
  7982. /******************************************************************************/
  7983.  
  7984. int
  7985. amiga_send(int fd,void *buff,size_t nbytes,int flags)
  7986. {
  7987.     struct UFB * ufb;
  7988.     int result = ERROR;
  7989.  
  7990.     ENTER();
  7991.  
  7992.     ufb = chkufb(fd);
  7993.     if(ufb != NULL && FLAG_IS_SET(ufb->ufbflg,UFB_IS_SOCKET))
  7994.         result = send(ufb->ufbfh,buff,nbytes,flags);
  7995.     else
  7996.         errno = EBADF;
  7997.  
  7998.     RETURN(result);
  7999.     return(result);
  8000. }
  8001.  
  8002. /******************************************************************************/
  8003.  
  8004. int
  8005. amiga_smbrun(char *cmd,char *outfile,BOOL shared)
  8006. {
  8007.     struct MangleInfo mi_cmd;
  8008.     struct MangleInfo mi_outfile;
  8009.     int result = ERROR;
  8010.  
  8011.     ENTER();
  8012.  
  8013.     ForbidDOS();
  8014.  
  8015.     if(outfile == NULL)
  8016.         outfile = "/dev/null";
  8017.  
  8018.     if(MangleName(&cmd,&mi_cmd) == OK)
  8019.     {
  8020.         if(MangleName(&outfile,&mi_outfile) == OK)
  8021.         {
  8022.             BPTR in;
  8023.  
  8024.             in = Open("NIL:",MODE_OLDFILE);
  8025.             if(in != ZERO)
  8026.             {
  8027.                 BPTR out;
  8028.  
  8029.                 out = Open(outfile,MODE_NEWFILE);
  8030.                 if(out != ZERO)
  8031.                 {
  8032.                     if(SystemTags(cmd,
  8033.                         SYS_Input,        in,
  8034.                         SYS_Output,        out,
  8035.                         SYS_UserShell,    TRUE,
  8036.                         NP_WindowPtr,    NULL,
  8037.                     TAG_DONE) != -1)
  8038.                     {
  8039.                         result = OK;
  8040.                     }
  8041.                     else
  8042.                     {
  8043.                         MapIoErrToErrno();
  8044.                     }
  8045.  
  8046.                     Close(out);
  8047.                 }
  8048.                 else
  8049.                 {
  8050.                     MapIoErrToErrno();
  8051.                 }
  8052.  
  8053.                 Close(in);
  8054.             }
  8055.             else
  8056.             {
  8057.                 MapIoErrToErrno();
  8058.             }
  8059.  
  8060.             UnmangleName(&outfile,&mi_outfile);
  8061.         }
  8062.  
  8063.         UnmangleName(&cmd,&mi_cmd);
  8064.     }
  8065.  
  8066.     PermitDOS();
  8067.  
  8068.     RETURN(result);
  8069.     return(result);
  8070. }
  8071.  
  8072. /******************************************************************************/
  8073.  
  8074. #define IFBSIZE 1024
  8075. #define max(a,b) ( (a) > (b) ? (a) : (b) )
  8076.  
  8077. int
  8078. amiga_get_interfaces(struct iface_struct * ifaces,int max_interfaces)
  8079. {
  8080.     struct ifreq * ifr_end;
  8081.     struct ifreq * ifr;
  8082.     struct ifconf * ifc;
  8083.     struct ifreq ifr_copy;
  8084.     int sockfd = -1;
  8085.     int result = -1;
  8086.     int total = 0;
  8087.     int len;
  8088.  
  8089.     /* Make room for the interface information. I hope
  8090.      * that 1024 bytes will be sufficient.
  8091.      */
  8092.     ifc = malloc(sizeof(*ifc) + IFBSIZE);
  8093.     if(ifc == NULL)
  8094.     {
  8095.         errno = ENOMEM;
  8096.         goto out;
  8097.     }
  8098.  
  8099.     sockfd = socket(AF_INET,SOCK_STREAM,0);
  8100.     if(sockfd < 0)
  8101.         goto out;
  8102.  
  8103.     /* Now attempt to copy the interface information into
  8104.      * the buffer. As of this writing, support for the
  8105.      * SIOCGIFCONF ioctl() action is undocumented in all
  8106.      * currently existing TCP/IP stacks. Nevertheless,
  8107.      * it appears to work.
  8108.      */
  8109.     ifc->ifc_len = IFBSIZE;
  8110.     ifc->ifc_buf = (char *)(ifc+1);
  8111.  
  8112.     if(IoctlSocket(sockfd,SIOCGIFCONF,(char *)ifc) != OK)
  8113.         goto out;
  8114.  
  8115.     len = ifc->ifc_len;
  8116.  
  8117.     ifr = (struct ifreq *)ifc->ifc_buf;
  8118.     ifr_end = (struct ifreq *)((char *)ifr + len);
  8119.  
  8120.     /* Now check each interface, extracting the interface
  8121.      * information.
  8122.      */
  8123.     while(ifr < ifr_end && total < max_interfaces)
  8124.     {
  8125.         ifr_copy = (*ifr);
  8126.  
  8127.         /* Try to obtain the address information. */
  8128.         if(IoctlSocket(sockfd,SIOCGIFADDR,(char *)&ifr_copy) == OK)
  8129.         {
  8130.             struct in_addr ipaddr;
  8131.  
  8132.             /* We need to remember this for later. */
  8133.             ipaddr = (*(struct sockaddr_in *)&ifr_copy.ifr_addr).sin_addr;
  8134.  
  8135.             /* And query the interface flags; in particular, we are interested
  8136.              * in whether this interface is currrently "up", i.e. "online".
  8137.              */
  8138.             if(IoctlSocket(sockfd,SIOCGIFFLAGS,(char *)&ifr_copy) == OK)
  8139.             {
  8140.                 if(ifr_copy.ifr_flags & IFF_UP)
  8141.                 {
  8142.                     /* And finally obtain the interface net mask. */
  8143.                     if(IoctlSocket(sockfd,SIOCGIFNETMASK,(char *)&ifr_copy) == OK)
  8144.                     {
  8145.                         struct in_addr nmask;
  8146.  
  8147.                         nmask = ((struct sockaddr_in *)&ifr_copy.ifr_addr)->sin_addr;
  8148.  
  8149.                         strncpy(ifaces[total].name, ifr_copy.ifr_name, sizeof(ifaces[total].name)-1);
  8150.                         ifaces[total].name[sizeof(ifaces[total].name)-1] = '\0';
  8151.  
  8152.                         ifaces[total].ip = ipaddr;
  8153.                         ifaces[total].netmask = nmask;
  8154.  
  8155.                         total++;
  8156.                     }
  8157.                 }
  8158.             }
  8159.         }
  8160.  
  8161.         len = max(sizeof(struct sockaddr),ifr->ifr_addr.sa_len);
  8162.         ifr = (struct ifreq *)(((char *)ifr) + sizeof(ifr->ifr_name) + len);
  8163.     }
  8164.  
  8165.     result = total;
  8166.  
  8167.  out:
  8168.  
  8169.     if(ifc != NULL)
  8170.         free(ifc);
  8171.  
  8172.     if(sockfd != -1)
  8173.         CloseSocket(sockfd);
  8174.  
  8175.     return(result);
  8176. }
  8177. @
  8178.  
  8179.  
  8180. 1.12
  8181. log
  8182. @.
  8183. @
  8184. text
  8185. @d2 1
  8186. a2 1
  8187.  * $Id: amiga.c 1.11 1999/11/06 16:03:15 olsen Exp olsen $
  8188. d7993 3
  8189. d8007 6
  8190. d8024 3
  8191. d8031 1
  8192. d8036 1
  8193. d8039 3
  8194. d8046 1
  8195. @
  8196.  
  8197.  
  8198. 1.11
  8199. log
  8200. @.
  8201. @
  8202. text
  8203. @d2 1
  8204. a2 1
  8205.  * $Id: amiga.c 1.10 1999/10/16 09:15:58 olsen Exp olsen $
  8206. d56 2
  8207. d85 5
  8208. d7973 88
  8209. @
  8210.  
  8211.  
  8212. 1.10
  8213. log
  8214. @.
  8215. @
  8216. text
  8217. @d2 1
  8218. a2 1
  8219.  * $Id: amiga.c 1.9 1999/08/09 15:28:43 olsen Exp olsen $
  8220. d36 1
  8221. d100 1
  8222. a100 1
  8223. STATIC int MangleName(char **namePtr, struct MangleInfo *mi);
  8224. d291 1
  8225. d1337 3
  8226. a1339 2
  8227.         /* Now check if the file name is longer than 30
  8228.          * characters. This is to avoid name space clashes.
  8229. d1341 1
  8230. a1341 1
  8231.         if(strlen(FilePart((STRPTR)name)) > 30)
  8232. d1343 61
  8233. a1403 2
  8234.             errno = ENAMETOOLONG; /* name is too long for us */
  8235.             goto out;
  8236. d4940 174
  8237. d5205 2
  8238. a5206 3
  8239.         char whichPatternBuffer[MAX_FILENAME_LEN];
  8240.         char *whichPattern = whichPatternBuffer;
  8241.         BOOL oldAllowBreak = AllowBreak;
  8242. d5208 1
  8243. a5208 2
  8244.         /* We don't want to be interrupted. */
  8245.         AllowBreak = FALSE;
  8246. d5210 5
  8247. a5214 2
  8248.         /* Now find the pattern to use. */
  8249.         nstrcpy_blank(sizeof(whichPatternBuffer),whichPattern,options);
  8250. d5216 2
  8251. a5217 3
  8252.         SHOWMSG("doing `ls'");
  8253.         SHOWSTRING(whichPattern);
  8254.         SHOWSTRING(redirectionFile);
  8255. d5219 2
  8256. a5220 5
  8257.         /* What happens next is that the contents of the
  8258.          * current directory are scanned. All file names
  8259.          * that match the given pattern are stored in the
  8260.          * redirection file.
  8261.          */
  8262. d5222 3
  8263. a5224 3
  8264.         if(MangleName(&redirectionFile,&mi) == OK)
  8265.         {
  8266.             FILE * out;
  8267. d5226 5
  8268. a5230 1
  8269.             ForbidDOS();
  8270. d5232 1
  8271. a5232 2
  8272.             out = fopen(redirectionFile,"wb");
  8273.             if(out != NULL)
  8274. d5234 1
  8275. a5234 1
  8276.                 BPTR dirLock;
  8277. d5236 4
  8278. a5239 2
  8279.                 dirLock = Lock("",SHARED_LOCK);
  8280.                 if(dirLock != ZERO)
  8281. d5241 31
  8282. a5271 1
  8283.                     struct FileInfoBlock __aligned fib;
  8284. d5273 4
  8285. a5276 1
  8286.                     if(Examine(dirLock,&fib))
  8287. d5278 1
  8288. a5278 1
  8289.                         BOOL stopped = FALSE;
  8290. d5280 4
  8291. a5283 1
  8292.                         while(ExNext(dirLock,&fib))
  8293. d5285 3
  8294. a5287 1
  8295.                             if(FIB_IS_FILE(&fib))
  8296. d5289 3
  8297. a5291 1
  8298.                                 if(do_match(fib.fib_FileName,whichPattern))
  8299. d5293 3
  8300. a5295 1
  8301.                                     if(fprintf(out,"%s\n",fib.fib_FileName) < 0)
  8302. d5297 11
  8303. a5307 2
  8304.                                         stopped = TRUE;
  8305.                                         break;
  8306. a5309 2
  8307.                             }
  8308.                         }
  8309. d5311 3
  8310. a5313 3
  8311.                         if(NOT stopped)
  8312.                         {
  8313.                             LONG error = IoErr();
  8314. d5315 10
  8315. a5324 3
  8316.                             if(error == ERROR_NO_MORE_ENTRIES)
  8317.                             {
  8318.                                 result = OK;
  8319. a5327 1
  8320.                                 SetIoErr(error);
  8321. d5330 6
  8322. a5337 4
  8323.                     else
  8324.                     {
  8325.                         MapIoErrToErrno();
  8326.                     }
  8327. d5339 4
  8328. a5342 5
  8329.                     UnLock(dirLock);
  8330.                 }
  8331.                 else
  8332.                 {
  8333.                     MapIoErrToErrno();
  8334. d5345 1
  8335. a5345 1
  8336.                 fclose(out);
  8337. d5347 1
  8338. a5347 2
  8339.                 if(result != OK)
  8340.                     DeleteFile(redirectionFile);
  8341. d5350 1
  8342. a5350 3
  8343.             PermitDOS();
  8344.  
  8345.             UnmangleName(&cmd,&mi);
  8346. a5351 2
  8347.  
  8348.         AllowBreak = oldAllowBreak;
  8349. d5360 4
  8350. d5456 2
  8351. a5457 2
  8352.                 struct MangleInfo mi;
  8353.                 BOOL hasDot;
  8354. d5459 1
  8355. a5459 1
  8356.                 hasDot = (BOOL)(strncmp(whichDrawer,"./",2) == SAME || strcmp(whichDrawer,".") == SAME);
  8357. d5461 1
  8358. a5461 1
  8359.                 if(MangleName(&whichDrawer,&mi) == OK)
  8360. d5463 1
  8361. a5463 1
  8362.                     BPTR dirLock;
  8363. d5465 1
  8364. a5465 2
  8365.                     dirLock = Lock(whichDrawer,SHARED_LOCK);
  8366.                     if(dirLock != ZERO)
  8367. d5467 1
  8368. a5467 1
  8369.                         struct FileInfoBlock __aligned fib;
  8370. d5469 3
  8371. a5471 1
  8372.                         if(Examine(dirLock,&fib))
  8373. d5473 3
  8374. a5475 8
  8375.                             struct AnchorPath * ap;
  8376.  
  8377.                             ap = malloc(sizeof(*ap) + MAX_FILENAME_LEN);
  8378.                             if(ap != NULL)
  8379.                             {
  8380.                                 BOOL stopped = FALSE;
  8381.                                 BPTR oldDir;
  8382.                                 LONG error;
  8383. d5477 1
  8384. a5477 1
  8385.                                 oldDir = CurrentDir(dirLock);
  8386. d5479 3
  8387. a5481 75
  8388.                                 memset(ap,0,sizeof(*ap) + MAX_FILENAME_LEN);
  8389.                                 ap->ap_Strlen        = MAX_FILENAME_LEN;
  8390.                                 ap->ap_BreakBits    = SIGBREAKF_CTRL_C;
  8391.  
  8392.                                 if((error = MatchFirst("",ap)) == OK)
  8393.                                 {
  8394.                                     do
  8395.                                     {
  8396.                                         D(("checking |%s|",ap->ap_Buf));
  8397.  
  8398.                                         if(FIB_IS_FILE(&ap->ap_Info))
  8399.                                         {
  8400.                                             SHOWMSG("this is a file");
  8401.                                             SHOWSTRING(ap->ap_Info.fib_FileName);
  8402.  
  8403.                                             if(do_match(ap->ap_Info.fib_FileName,whichPattern))
  8404.                                             {
  8405.                                                 D(("Output |%s/%s|",whichDrawerBuffer,ap->ap_Buf));
  8406.                                                 if(fprintf(out,"%s%s/%s\n",(hasDot) ? "./" : "",whichDrawerBuffer,ap->ap_Buf) < 0)
  8407.                                                 {
  8408.                                                     stopped = TRUE;
  8409.                                                     break;
  8410.                                                 }
  8411.                                             }
  8412.                                             else
  8413.                                             {
  8414.                                                 SHOWMSG("but its name does not match");
  8415.                                             }
  8416.                                         }
  8417.                                         else
  8418.                                         {
  8419.                                             SHOWMSG("this is a drawer");
  8420.  
  8421.                                             if(FLAG_IS_CLEAR(ap->ap_Flags,APF_DIDDIR))
  8422.                                                 SET_FLAG(ap->ap_Flags,APF_DODIR);
  8423.                                             else
  8424.                                                 CLEAR_FLAG(ap->ap_Flags,APF_DIDDIR);
  8425.                                         }
  8426.                                     }
  8427.                                     while((error = MatchNext(ap)) == OK);
  8428.                                 }
  8429.  
  8430.                                 MatchEnd(ap);
  8431.  
  8432.                                 CurrentDir(oldDir);
  8433.  
  8434.                                 if(NOT stopped)
  8435.                                 {
  8436.                                     if(error == ERROR_NO_MORE_ENTRIES)
  8437.                                     {
  8438.                                         result = OK;
  8439.                                     }
  8440.                                     else if(error == ERROR_BREAK)
  8441.                                     {
  8442.                                         /* Don't do anything; we are going
  8443.                                          * to delete the file anyway.
  8444.                                          */
  8445.                                     }
  8446.                                     else
  8447.                                     {
  8448.                                         SetIoErr(error);
  8449.                                         MapIoErrToErrno();
  8450.                                     }
  8451.                                 }
  8452.  
  8453.                                 free(ap);
  8454.                             }
  8455.                             else
  8456.                             {
  8457.                                 errno = ENOMEM;
  8458.                             }
  8459.                         }
  8460.                         else
  8461.                         {
  8462.                             MapIoErrToErrno();
  8463. d5484 2
  8464. a5485 1
  8465.                         UnLock(dirLock);
  8466. d5489 3
  8467. a5491 1
  8468.                         MapIoErrToErrno();
  8469. a5492 2
  8470.  
  8471.                     UnmangleName(&whichDrawer,&mi);
  8472. d7894 70
  8473. @
  8474.  
  8475.  
  8476. 1.9
  8477. log
  8478. @.
  8479. @
  8480. text
  8481. @d2 1
  8482. a2 1
  8483.  * $Id: amiga.c 1.8 1999/05/21 09:38:15 olsen Exp olsen $
  8484. d315 10
  8485. d326 30
  8486. a355 1
  8487. char * VersionTag = VERSTAG " Samba version 2.0.0 ported by Olaf `Olsen' Barthel <olsen@@sourcery.han.de>";
  8488. d5164 3
  8489. d5208 1
  8490. a5208 1
  8491.                                                 if(fprintf(out,"%s/%s\n",whichDrawerBuffer,ap->ap_Buf) < 0)
  8492. a5964 2
  8493. #define SEEK_ERROR (-1)
  8494.  
  8495. a5980 1
  8496.     {
  8497. a5981 55
  8498.  
  8499.         /* Now comes the tricky bit; check if the lseek() call
  8500.          * was meant to *extend* the file.
  8501.          */
  8502.         if(result != OK)
  8503.         {
  8504.             struct FileInfoBlock __aligned fib;
  8505.  
  8506.             if(ExamineFH((BPTR)ufb->ufbfh,&fib))
  8507.             {
  8508.                 off_t new_offset = 0;
  8509.                 BOOL good = FALSE;
  8510.  
  8511.                 switch(mode)
  8512.                 {
  8513.                     case SEEK_SET:
  8514.  
  8515.                         new_offset = offset;
  8516.                         good = TRUE;
  8517.                         break;
  8518.  
  8519.                     case SEEK_CUR:
  8520.  
  8521.                         new_offset = Seek((BPTR)ufb->ufbfh,0,OFFSET_CURRENT);
  8522.                         if(new_offset != SEEK_ERROR)
  8523.                         {
  8524.                             new_offset += offset;
  8525.                             good = TRUE;
  8526.                         }
  8527.  
  8528.                         break;
  8529.  
  8530.                     case SEEK_END:
  8531.  
  8532.                         new_offset = fib.fib_Size + offset;
  8533.                         good = TRUE;
  8534.                         break;
  8535.                 }
  8536.  
  8537.                 if(good)
  8538.                 {
  8539.                     if(new_offset > fib.fib_Size)
  8540.                     {
  8541.                         /* Make the file larger; according to the BSD
  8542.                          * documentation, we should fill the newly
  8543.                          * allocated file area with zeroes. I'm not
  8544.                          * sure whether this belongs here.
  8545.                          */
  8546.                         if(SetFileSize((BPTR)ufb->ufbfh,new_offset,OFFSET_BEGINNING) != SET_FILESIZE_ERROR)
  8547.                             result = lseek(fd,offset,mode);
  8548.                     }
  8549.                 }
  8550.             }
  8551.         }
  8552.     }
  8553. a5982 1
  8554.     {
  8555. a5983 1
  8556.     }
  8557. d7047 1
  8558. a7047 1
  8559.                                 ObtainSemaphoreShared((struct SignalSemaphore *)SambaSemaphore);
  8560. @
  8561.  
  8562.  
  8563. 1.8
  8564. log
  8565. @.
  8566. @
  8567. text
  8568. @d2 1
  8569. a2 1
  8570.  * $Id: amiga.c 1.7 1999/05/02 10:45:08 olsen Exp olsen $
  8571. a216 2
  8572. VOID _CXOVF(VOID);
  8573. VOID __regargs _CXBRK(VOID);
  8574. a275 1
  8575. #define FIB_IS_DRAWER(fib)    ((fib)->fib_DirEntryType > 0)
  8576. d277 1
  8577. d316 1
  8578. a316 1
  8579. char * VersionTag = VERSTAG " Samba version 2.0.3 ported by Olaf `Olsen' Barthel <olsen@@sourcery.han.de>";
  8580. d7657 40
  8581. @
  8582.  
  8583.  
  8584. 1.7
  8585. log
  8586. @.
  8587. @
  8588. text
  8589. @d2 1
  8590. a2 1
  8591.  * $Id: amiga.c 1.6 1999/02/28 09:16:53 olsen Exp olsen $
  8592. d34 1
  8593. d1793 1
  8594. a1793 3
  8595.  
  8596.                 /* Is there a filing system mounted here? */
  8597.                 while(dol != NULL && dol->dol_Task != NULL)
  8598. d1795 4
  8599. a1798 4
  8600.                     struct InfoData __aligned id;
  8601.  
  8602.                     /* Is there a disk present? */
  8603.                     if(DoPkt(dol->dol_Task,ACTION_DISK_INFO,MKBADDR(&id),    0,0,0,0))
  8604. d1800 1
  8605. a1800 2
  8606.                         char *name = BADDR(dol->dol_Name);
  8607.                         struct Node * node;
  8608. d1802 2
  8609. a1803 5
  8610.                         /* Collect the number of blocks used and
  8611.                          * available in our fake root directory.
  8612.                          * Not that it matters much...
  8613.                          */
  8614.                         if(id.id_BytesPerBlock == 512)
  8615. d1805 17
  8616. a1821 8
  8617.                             RootBlocks        += id.id_NumBlocks;
  8618.                             RootBlocksUsed    += id.id_NumBlocksUsed;
  8619.                         }
  8620.                         else
  8621.                         {
  8622.                             RootBlocks        += (id.id_NumBlocks * id.id_BytesPerBlock) / 512;
  8623.                             RootBlocksUsed    += (id.id_NumBlocksUsed * id.id_BytesPerBlock) / 512;
  8624.                         }
  8625. d1823 7
  8626. a1829 7
  8627.                         node = malloc(sizeof(*node) + name[0]+1);
  8628.                         if(node != NULL)
  8629.                         {
  8630.                             /* Copy the name of the volume. */
  8631.                             node->ln_Name = (char *)(node + 1);
  8632.                             strncpy(node->ln_Name,&name[1],name[0]);
  8633.                             node->ln_Name[ name[0] ] = '\0';
  8634. d1831 1
  8635. a1831 1
  8636.                             AddTail(&odn->odn_VolumeList,node);
  8637. d1833 3
  8638. a1835 2
  8639.                             if(odn->odn_NextNode == NULL)
  8640.                                 odn->odn_NextNode = node;
  8641. d2338 1
  8642. a2338 1
  8643.      * it is first removed.Both <from> and <to> must be of the same type (that is,
  8644. d2471 1
  8645. a2471 1
  8646.     
  8647. d5957 1
  8648. a5957 1
  8649.     
  8650. d5961 1
  8651. a5961 1
  8652.     
  8653. d5965 1
  8654. a5965 1
  8655.     
  8656. d5967 1
  8657. a5967 1
  8658.     
  8659. d5976 1
  8660. a5976 1
  8661.     
  8662. d5978 1
  8663. a5978 1
  8664.     
  8665. d5983 1
  8666. a5983 1
  8667.     
  8668. @
  8669.  
  8670.  
  8671. 1.6
  8672. log
  8673. @.
  8674. @
  8675. text
  8676. @d2 1
  8677. a2 1
  8678.  * $Id: amiga.c 1.5 1999/02/22 15:31:18 olsen Exp olsen $
  8679. d81 1
  8680. d316 2
  8681. a317 2
  8682. #include "Amiga_Samba_2.0.0_rev.h"
  8683. char * VersionTag = VERSTAG " Ported by Olaf `Olsen' Barthel <olsen@@sourcery.han.de>";
  8684. d473 1
  8685. d487 74
  8686. a560 1
  8687.             EasyRequestArgs(NULL,&es,NULL,(APTR)varArgs);
  8688. d987 1
  8689. a987 1
  8690.     /* Initialize up the current time zone variable. */
  8691. d1170 2
  8692. a1171 1
  8693.             if(name[i] == '.')
  8694. d2332 6
  8695. d2343 65
  8696. a2407 1
  8697.             result = rename(old,new);
  8698. d2412 4
  8699. d2419 4
  8700. a2433 1
  8701.     BPTR oldDir;
  8702. d2443 1
  8703. a2443 5
  8704.     ForbidDOS();
  8705.  
  8706.     oldDir = CurrentDir(ZERO);
  8707.  
  8708.     if(NameFromLock(oldDir,buf,size))
  8709. d2445 3
  8710. a2447 2
  8711.         if(MapFileNameAmigaToUnix(buf,buf,size) == OK)
  8712.             result = buf;
  8713. d2451 5
  8714. a2455 2
  8715.         MapIoErrToErrno();
  8716.     }
  8717. d2457 11
  8718. a2467 1
  8719.     CurrentDir(oldDir);
  8720. d2469 2
  8721. a2470 1
  8722.     PermitDOS();
  8723. d3538 1
  8724. a3538 1
  8725.                 /* Nobody can write to this "directory". */
  8726. d3610 42
  8727. a3651 1
  8728.                     MapIoErrToErrno();
  8729. d3853 1
  8730. d3855 1
  8731. d3857 18
  8732. a3874 1
  8733.             MapIoErrToErrno();
  8734. d4024 1
  8735. a4024 1
  8736.         /* AmigaDOS 3.0 and up has a SetOwner() call. */
  8737. d4168 1
  8738. d4170 1
  8739. d4172 18
  8740. a4189 1
  8741.             MapIoErrToErrno();
  8742. d4769 1
  8743. a4769 1
  8744.             /* Look for a character matching  the one after the '*' */
  8745. d4805 1
  8746. a4805 1
  8747.     if((*p) == '\0' && str[0] == '.' && str[1] == 0)
  8748. d4941 6
  8749. d5102 10
  8750. d5140 1
  8751. d5143 2
  8752. d5189 2
  8753. d5920 2
  8754. d5933 2
  8755. d5938 1
  8756. d5940 55
  8757. d5996 1
  8758. d5998 3
  8759. d6179 1
  8760. a6179 1
  8761. STATIC STRPTR SambaSemaphoreName = "Amiga Samba 2.0.0";
  8762. d6725 1
  8763. a6725 1
  8764.      * This means for example, that every unlock request must
  8765. d7266 2
  8766. d7287 1
  8767. @
  8768.  
  8769.  
  8770. 1.5
  8771. log
  8772. @.
  8773. @
  8774. text
  8775. @d2 1
  8776. a2 1
  8777.  * $Id: amiga.c 1.4 1999/02/21 10:58:42 olsen Exp olsen $
  8778. d868 1
  8779. d891 4
  8780. a4607 2
  8781.     PUSH_ALL();
  8782.  
  8783. a4993 1
  8784.     POP();
  8785. d6044 3
  8786. d6051 1
  8787. d6068 3
  8788. d6133 4
  8789. d6183 4
  8790. d6211 3
  8791. d6254 4
  8792. d6299 5
  8793. d6308 1
  8794. d6311 3
  8795. d6316 5
  8796. a6320 1
  8797.                 if(NOT shared && NOT lrn->lrn_Shared && lrn->lrn_Owner == ThisClient->scn_PID)
  8798. d6323 3
  8799. d6340 4
  8800. a6349 2
  8801.         PUSH_ALL();
  8802.  
  8803. a6382 2
  8804.  
  8805.         POP();
  8806. d6393 12
  8807. a6404 3
  8808.     PUSH_ALL();
  8809.  
  8810.     /* Check for proper input. */
  8811. d6565 1
  8812. a6565 1
  8813.                                                 SHOWMSG("that file is already locked by someone else");
  8814. d6598 3
  8815. d6607 13
  8816. a6619 1
  8817.                                                 Delay(TICKS_PER_SECOND / 2);
  8818. a6833 2
  8819.     POP();
  8820.  
  8821. d7278 1
  8822. a7278 1
  8823.     int result;
  8824. @
  8825.  
  8826.  
  8827. 1.4
  8828. log
  8829. @.
  8830. @
  8831. text
  8832. @d2 1
  8833. a2 1
  8834.  * $Id: amiga.c 1.3 1999/02/20 17:52:48 olsen Exp olsen $
  8835. d98 1
  8836. a98 1
  8837. STATIC VOID CloseUnlinkCleanup(VOID);
  8838. d104 2
  8839. a108 1
  8840. STATIC int LockTheFile(int cmd, struct flock *l, struct UFB *ufb);
  8841. d114 10
  8842. d284 1
  8843. d322 10
  8844. d335 1
  8845. a335 1
  8846.     if(AllowBreak && FLAG_IS_SET(SetSignal(0,SIGBREAKF_CTRL_C),SIGBREAKF_CTRL_C))
  8847. d926 1
  8848. a926 1
  8849.     CloseUnlinkCleanup();
  8850. d1242 1
  8851. a1242 1
  8852. CloseUnlinkCleanup(VOID)
  8853. d1253 2
  8854. a1254 3
  8855.     /* We look for descriptors we switched into
  8856.      * non-blocking mode and reset them back
  8857.      * to blocking mode.
  8858. d1258 2
  8859. d1269 1
  8860. d2447 2
  8861. a5368 276
  8862. #define SEEK_ERROR (-1)
  8863.  
  8864. STATIC int
  8865. LockTheFile(int cmd,struct flock * l,struct UFB * ufb)
  8866. {
  8867.     int result = ERROR;
  8868.  
  8869.     /* Check for proper input. */
  8870.     if(l != NULL && ufb != NULL)
  8871.     {
  8872.         /* Can we make sense of the input parameters? */
  8873.         if(F_RDLCK <= l->l_type && l->l_type <= F_WRLCK &&
  8874.           (l->l_whence == SEEK_SET || l->l_whence == SEEK_CUR || l->l_whence == SEEK_END))
  8875.         {
  8876.             struct FileInfoBlock __aligned fib;
  8877.             BOOL dataIsValid = TRUE;
  8878.             LONG currentPosition;
  8879.             LONG start = 0;
  8880.             LONG len = 0;
  8881.  
  8882.             /* Now calculate the position of the
  8883.              * first byte to lock and the number
  8884.              * of bytes to lock.
  8885.              */
  8886.             switch(l->l_whence)
  8887.             {
  8888.                 case SEEK_SET:
  8889.  
  8890.                     start = l->l_start;
  8891.  
  8892.                     if(l->l_len == 0)
  8893.                     {
  8894.                         if(ExamineFH((BPTR)ufb->ufbfh,&fib))
  8895.                             len = fib.fib_Size - start;
  8896.                         else
  8897.                             dataIsValid = FALSE;
  8898.                     }
  8899.                     else
  8900.                     {
  8901.                         len = l->l_len;
  8902.                     }
  8903.  
  8904.                     break;
  8905.  
  8906.                 case SEEK_CUR:
  8907.  
  8908.                     currentPosition = Seek((BPTR)ufb->ufbfh,0,OFFSET_CURRENT);
  8909.                     if(currentPosition != SEEK_ERROR)
  8910.                     {
  8911.                         start = currentPosition + l->l_start;
  8912.  
  8913.                         if(l->l_len == 0)
  8914.                         {
  8915.                             if(ExamineFH((BPTR)ufb->ufbfh,&fib))
  8916.                                 len = fib.fib_Size - start;
  8917.                             else
  8918.                                 dataIsValid = FALSE;
  8919.                         }
  8920.                         else
  8921.                         {
  8922.                             len = l->l_len;
  8923.                         }
  8924.                     }
  8925.                     else
  8926.                     {
  8927.                         dataIsValid = FALSE;
  8928.                     }
  8929.  
  8930.                     break;
  8931.  
  8932.                 case SEEK_END:
  8933.                 default:
  8934.  
  8935.                     if(ExamineFH((BPTR)ufb->ufbfh,&fib))
  8936.                     {
  8937.                         start = fib.fib_Size + l->l_start;
  8938.  
  8939.                         if(l->l_len == 0)
  8940.                             len = fib.fib_Size - start;
  8941.                         else
  8942.                             len = l->l_len;
  8943.                     }
  8944.                     else
  8945.                     {
  8946.                         dataIsValid = FALSE;
  8947.                     }
  8948.  
  8949.                     break;
  8950.             }
  8951.  
  8952.             SHOWVALUE(start);
  8953.             SHOWVALUE(len);
  8954.  
  8955.             /* Did we get everything we needed? */
  8956.             if(dataIsValid)
  8957.             {
  8958.                 if(start >= 0 && len >= 0)
  8959.                 {
  8960.                     if(len > 0)
  8961.                     {
  8962.                         if(l->l_type == F_UNLCK)
  8963.                         {
  8964.                             D(("unlocking %ld..%ld",start,start+len-1));
  8965.  
  8966.                             if(UnLockRecord((BPTR)ufb->ufbfh,start,len))
  8967.                                 result = OK;
  8968.                             else
  8969.                                 MapIoErrToErrno();
  8970.                         }
  8971.                         else
  8972.                         {
  8973.                             D(("  locking %ld..%ld",start,start+len-1));
  8974.  
  8975.                             if(cmd == F_SETLKW)
  8976.                             {
  8977.                                 LONG mode = (l->l_type == F_WRLCK) ? REC_EXCLUSIVE : REC_SHARED;
  8978.  
  8979.                                 if(mode == REC_EXCLUSIVE)
  8980.                                     D(("this is an exclusive lock; waiting for completion"));
  8981.                                 else
  8982.                                     D(("this is a shared lock; waiting for completion"));
  8983.  
  8984.                                 /* Retry until we manage to lock the record. */
  8985.                                 while(CANNOT LockRecord((BPTR)ufb->ufbfh,start,len,mode,TICKS_PER_SECOND / 2))
  8986.                                     chkabort();
  8987.  
  8988.                                 result = OK;
  8989.                             }
  8990.                             else
  8991.                             {
  8992.                                 LONG mode = (l->l_type == F_WRLCK) ? REC_EXCLUSIVE_IMMED : REC_SHARED_IMMED;
  8993.  
  8994.                                 if(mode == REC_EXCLUSIVE_IMMED)
  8995.                                     D(("this is an exclusive lock"));
  8996.                                 else
  8997.                                     D(("this is a shared lock"));
  8998.  
  8999.                                 if(LockRecord((BPTR)ufb->ufbfh,start,len,mode,0))
  9000.                                     result = OK;
  9001.                                 else
  9002.                                     MapIoErrToErrno();
  9003.                             }
  9004.                         }
  9005.                     }
  9006.                     else
  9007.                     {
  9008.                         SHOWMSG("zero length lock/unlock");
  9009.                         result = OK;
  9010.                     }
  9011.                 }
  9012.                 else
  9013.                 {
  9014.                     SHOWMSG("invalid start/len");
  9015.                     SHOWVALUE(start);
  9016.                     SHOWVALUE(len);
  9017.                     errno = EINVAL;
  9018.                 }
  9019.             }
  9020.             else
  9021.             {
  9022.                 SHOWMSG("couldn't determine start/len");
  9023.                 MapIoErrToErrno();
  9024.             }
  9025.         }
  9026.         else
  9027.         {
  9028.             SHOWMSG("invalid lock type or seek offset");
  9029.             SHOWVALUE(l->l_type);
  9030.             SHOWVALUE(l->l_whence);
  9031.             errno = EINVAL;
  9032.         }
  9033.     }
  9034.     else
  9035.     {
  9036.         SHOWMSG("no flock or no ufb");
  9037.         SHOWVALUE(l);
  9038.         SHOWVALUE(ufb);
  9039.  
  9040.         errno = EINVAL;
  9041.     }
  9042.  
  9043.     return(result);
  9044. }
  9045.  
  9046. int
  9047. amiga_fcntl(int fd,int cmd,unsigned long arg)
  9048. {
  9049.     struct UFB * ufb;
  9050.     struct flock * l;
  9051.     int result = ERROR;
  9052.  
  9053.     chkabort();
  9054.  
  9055.     ENTER();
  9056.  
  9057.     /* Don't try to lock data in a socket... */
  9058.     ufb = chkufb(fd);
  9059.     if(ufb == NULL || FLAG_IS_SET(ufb->ufbflg,UFB_IS_SOCKET))
  9060.         ufb = NULL;
  9061.  
  9062.     l = (struct flock *)arg;
  9063.  
  9064.     switch(cmd)
  9065.     {
  9066.         /* Get the first lock that blocks the lock description pointed to
  9067.          * by the third argument, arg, taken as a pointer to a struct
  9068.          * flock (see above).  The information retrieved overwrites the
  9069.          * information passed to fcntl in the flock structure.  If no
  9070.          * lock is found that would prevent this lock from being created,
  9071.          * the structure is left unchanged by this function call except
  9072.          * for the lock type which is set to F_UNLCK.
  9073.          */
  9074.         case F_GETLK:
  9075.  
  9076.             SHOWMSG("F_GETLK");
  9077.             errno = ENOSYS;
  9078.             break;
  9079.  
  9080.         /* Set or clear a file segment lock according to the lock de-
  9081.          * scription pointed to by the third argument, arg, taken as a
  9082.          * pointer to a struct flock (see above).    F_SETLK is used to es-
  9083.          * tablish shared (or read) locks (F_RDLCK) or exclusive (or
  9084.          * write) locks, (F_WRLCK), as well as remove either type of lock
  9085.          * (F_UNLCK). If a shared or exclusive lock cannot be set, fcntl
  9086.          * returns immediately with EACCES.
  9087.          */
  9088.         case F_SETLK:
  9089.  
  9090.             result = LockTheFile(cmd,l,ufb);
  9091.             break;
  9092.  
  9093.         /* This command is the same as F_SETLK except that if a shared or
  9094.          * exclusive lock is blocked by other locks, the process waits
  9095.          * until the request can be satisfied.  If a signal that is to be
  9096.          * caught is received while fcntl is waiting for a region, the
  9097.          * fcntl will be interrupted if the signal handler has not speci-
  9098.          * fied the SA_RESTART (see sigaction(2)).
  9099.          */
  9100.         case F_SETLKW:
  9101.  
  9102.             result = LockTheFile(cmd,l,ufb);
  9103.             break;
  9104.  
  9105.         /* Get descriptor status flags, as described below (arg is ig-
  9106.          * noted).
  9107.          */
  9108.         case F_GETFL:
  9109.  
  9110.             result = IsDescriptorNonblocking(fd) ? O_NONBLOCK : 0;
  9111.             break;
  9112.  
  9113.         /* Set descriptor status flags to arg. */
  9114.         case F_SETFL:
  9115.  
  9116.             if(FLAG_IS_SET(arg,O_NONBLOCK))
  9117.                 BlockDescriptor(fd);
  9118.             else
  9119.                 UnblockDescriptor(fd);
  9120.  
  9121.             result = OK;
  9122.             break;
  9123.  
  9124.         default:
  9125.  
  9126.             D(("Unknown command %ld",cmd));
  9127.             result = ERROR;
  9128.             errno = ENOSYS;
  9129.             break;
  9130.     }
  9131.  
  9132.     RETURN(result);
  9133.     return(result);
  9134. }
  9135.  
  9136. /******************************************************************************/
  9137.  
  9138. d5863 1
  9139. d5912 5
  9140. d6010 853
  9141. @
  9142.  
  9143.  
  9144. 1.3
  9145. log
  9146. @.
  9147. @
  9148. text
  9149. @d2 1
  9150. a2 1
  9151.  * $Id: amiga.c 1.2 1999/02/20 16:52:05 olsen Exp olsen $
  9152. d222 2
  9153. d6599 53
  9154. @
  9155.  
  9156.  
  9157. 1.2
  9158. log
  9159. @.
  9160. @
  9161. text
  9162. @d2 1
  9163. a2 1
  9164.  * $Id: amiga.c 1.1 1999/02/13 15:32:16 olsen Exp olsen $
  9165. d4476 70
  9166. d4676 1
  9167. a4676 1
  9168.                 struct MangleInfo mi;
  9169. d4678 2
  9170. a4679 1
  9171.                 if(MangleName(&whichPattern,&mi) == OK)
  9172. d4681 1
  9173. a4681 1
  9174.                     BPTR dirLock;
  9175. d4683 1
  9176. a4683 2
  9177.                     dirLock = Lock("",SHARED_LOCK);
  9178.                     if(dirLock != ZERO)
  9179. d4685 1
  9180. a4685 1
  9181.                         struct AnchorPath * ap;
  9182. d4687 1
  9183. a4687 2
  9184.                         ap = malloc(sizeof(*ap) + MAX_FILENAME_LEN);
  9185.                         if(ap != NULL)
  9186. d4689 1
  9187. a4689 8
  9188.                             BOOL stopped = FALSE;
  9189.                             LONG error;
  9190.  
  9191.                             memset(ap,0,sizeof(*ap) + MAX_FILENAME_LEN);
  9192.                             ap->ap_Strlen        = MAX_FILENAME_LEN;
  9193.                             ap->ap_BreakBits    = SIGBREAKF_CTRL_C;
  9194.  
  9195.                             if((error = MatchFirst(whichPattern,ap)) == OK)
  9196. d4691 1
  9197. a4691 13
  9198.                                 SHOWSTRING(ap->ap_Info.fib_FileName);
  9199.  
  9200.                                 if(FIB_IS_DRAWER(&ap->ap_Info))
  9201.                                 {
  9202.                                     SHOWMSG("this is a drawer");
  9203.                                     SET_FLAG(ap->ap_Flags,APF_DODIR);
  9204.                                 }
  9205.                                 else
  9206.                                 {
  9207.                                     SHOWMSG("this is not a drawer");
  9208.                                 }
  9209.  
  9210.                                 do
  9211. d4693 1
  9212. a4693 10
  9213.                                     if(FIB_IS_FILE(&ap->ap_Info))
  9214.                                     {
  9215.                                         D(("Output |%s|",ap->ap_Buf));
  9216.                                         if(fprintf(out,"%s\n",ap->ap_Buf) < 0)
  9217.                                         {
  9218.                                             stopped = TRUE;
  9219.                                             break;
  9220.                                         }
  9221.                                     }
  9222.                                     else
  9223. d4695 2
  9224. a4696 1
  9225.                                         CLEAR_FLAG(ap->ap_Flags,APF_DIDDIR);
  9226. a4698 1
  9227.                                 while((error = MatchNext(ap)) == OK);
  9228. d4700 1
  9229. d4702 3
  9230. a4704 1
  9231.                             MatchEnd(ap);
  9232. d4706 1
  9233. a4706 1
  9234.                             if(NOT stopped)
  9235. d4708 6
  9236. a4713 15
  9237.                                 if(error == ERROR_NO_MORE_ENTRIES)
  9238.                                 {
  9239.                                     result = OK;
  9240.                                 }
  9241.                                 else if(error == ERROR_BREAK)
  9242.                                 {
  9243.                                     /* Don't do anything; we are going
  9244.                                      * to delete the file anyway.
  9245.                                      */
  9246.                                 }
  9247.                                 else
  9248.                                 {
  9249.                                     SetIoErr(error);
  9250.                                     MapIoErrToErrno();
  9251.                                 }
  9252. a4714 6
  9253.  
  9254.                             free(ap);
  9255.                         }
  9256.                         else
  9257.                         {
  9258.                             errno = ENOMEM;
  9259. a4715 2
  9260.  
  9261.                         UnLock(dirLock);
  9262. d4722 5
  9263. a4726 1
  9264.                     UnmangleName(&whichPattern,&mi);
  9265. d4831 1
  9266. a4831 2
  9267.                 char compiledPattern[2 * (MAX_FILENAME_LEN+1)];
  9268.                 LONG isWild;
  9269. d4833 1
  9270. a4833 3
  9271.                 isWild = ParsePatternNoCase(whichPattern,compiledPattern,sizeof(compiledPattern));
  9272.                 SHOWVALUE(isWild);
  9273.                 if(isWild != -1)
  9274. d4835 1
  9275. a4835 1
  9276.                     struct MangleInfo mi;
  9277. d4837 2
  9278. a4838 1
  9279.                     if(MangleName(&whichDrawer,&mi) == OK)
  9280. d4840 1
  9281. a4840 1
  9282.                         BPTR dirLock;
  9283. d4842 1
  9284. a4842 2
  9285.                         dirLock = Lock(whichDrawer,SHARED_LOCK);
  9286.                         if(dirLock != ZERO)
  9287. d4844 1
  9288. a4844 1
  9289.                             struct FileInfoBlock __aligned fib;
  9290. d4846 2
  9291. a4847 1
  9292.                             if(Examine(dirLock,&fib))
  9293. d4849 2
  9294. a4850 1
  9295.                                 struct AnchorPath * ap;
  9296. d4852 5
  9297. a4856 2
  9298.                                 ap = malloc(sizeof(*ap) + MAX_FILENAME_LEN);
  9299.                                 if(ap != NULL)
  9300. d4858 3
  9301. a4860 2
  9302.                                     BOOL stopped = FALSE;
  9303.                                     LONG error;
  9304. d4862 1
  9305. a4862 7
  9306.                                     memset(ap,0,sizeof(*ap) + MAX_FILENAME_LEN);
  9307.                                     ap->ap_Strlen        = MAX_FILENAME_LEN;
  9308.                                     ap->ap_BreakBits    = SIGBREAKF_CTRL_C;
  9309.  
  9310.                                     if((error = MatchFirst("",ap)) == OK)
  9311.                                     {
  9312.                                         do
  9313. d4864 2
  9314. a4865 1
  9315.                                             D(("checking |%s|",ap->ap_Buf));
  9316. d4867 1
  9317. a4867 1
  9318.                                             if(FIB_IS_FILE(&ap->ap_Info))
  9319. d4869 2
  9320. a4870 4
  9321.                                                 SHOWMSG("this is a file");
  9322.                                                 SHOWSTRING(ap->ap_Info.fib_FileName);
  9323.  
  9324.                                                 if(MatchPatternNoCase(compiledPattern,ap->ap_Info.fib_FileName))
  9325. d4872 2
  9326. a4873 10
  9327.                                                     D(("Output |%s/%s|",whichDrawerBuffer,ap->ap_Buf));
  9328.                                                     if(fprintf(out,"%s/%s\n",whichDrawerBuffer,ap->ap_Buf) < 0)
  9329.                                                     {
  9330.                                                         stopped = TRUE;
  9331.                                                         break;
  9332.                                                     }
  9333.                                                 }
  9334.                                                 else
  9335.                                                 {
  9336.                                                     SHOWMSG("but its name does not match");
  9337. d4878 1
  9338. a4878 6
  9339.                                                 SHOWMSG("this is a drawer");
  9340.  
  9341.                                                 if(FLAG_IS_CLEAR(ap->ap_Flags,APF_DIDDIR))
  9342.                                                     SET_FLAG(ap->ap_Flags,APF_DODIR);
  9343.                                                 else
  9344.                                                     CLEAR_FLAG(ap->ap_Flags,APF_DIDDIR);
  9345. a4880 17
  9346.                                         while((error = MatchNext(ap)) == OK);
  9347.                                     }
  9348.  
  9349.                                     MatchEnd(ap);
  9350.  
  9351.                                     if(NOT stopped)
  9352.                                     {
  9353.                                         if(error == ERROR_NO_MORE_ENTRIES)
  9354.                                         {
  9355.                                             result = OK;
  9356.                                         }
  9357.                                         else if(error == ERROR_BREAK)
  9358.                                         {
  9359.                                             /* Don't do anything; we are going
  9360.                                              * to delete the file anyway.
  9361.                                              */
  9362.                                         }
  9363. d4883 6
  9364. a4888 2
  9365.                                             SetIoErr(error);
  9366.                                             MapIoErrToErrno();
  9367. d4891 4
  9368. d4896 1
  9369. a4896 3
  9370.                                     free(ap);
  9371.                                 }
  9372.                                 else
  9373. d4898 15
  9374. a4912 1
  9375.                                     errno = ENOMEM;
  9376. d4914 2
  9377. d4919 1
  9378. a4919 1
  9379.                                 MapIoErrToErrno();
  9380. a4920 2
  9381.  
  9382.                             UnLock(dirLock);
  9383. d4927 1
  9384. a4927 1
  9385.                         UnmangleName(&whichDrawer,&mi);
  9386. d4929 6
  9387. a4934 4
  9388.                 }
  9389.                 else
  9390.                 {
  9391.                     MapIoErrToErrno();
  9392. @
  9393.  
  9394.  
  9395. 1.1
  9396. log
  9397. @.
  9398. @
  9399. text
  9400. @d221 1
  9401. d1006 9
  9402. a1014 2
  9403.                 /* Convert any "/dev/" reference to "NIL:". */
  9404.                 name = "NIL:";
  9405. d1303 2
  9406. d1489 1
  9407. a1489 1
  9408.     BOOL isAbsolutePath = FALSE;
  9409. d4476 14
  9410. d4493 2
  9411. d4497 5
  9412. d4505 2
  9413. d4512 420
  9414. a4931 1
  9415.     if(MangleName(&cmd,&mi) == OK)
  9416. d4933 5
  9417. a4937 3
  9418.         ForbidDOS();
  9419.         result = system(cmd);
  9420.         PermitDOS();
  9421. d4939 2
  9422. a4940 1
  9423.         UnmangleName(&cmd,&mi);
  9424. d4944 1
  9425. d6244 1
  9426. a6244 1
  9427.     int result;
  9428. d6256 1
  9429. a6256 2
  9430.         result = recv(ufb->ufbfh,&c,1,0);
  9431.         if(result == 1)
  9432. a6257 2
  9433.  
  9434.         RETURN(result);
  9435. d6264 1
  9436. d6272 1
  9437. a6272 1
  9438.     char *result = NULL;
  9439. d6381 1
  9440. d6553 22
  9441. @
  9442.